post

ASP.NET Core updates in .NET Core 3.0 Preview 5

Avatar

.NET Core 3.0 Preview 5 is now available. This iteration was brief for the team and primarily includes bug fixes and improvements to the more significant updates in Preview 4. This post summarizes the important points in this release.

Please see the release notes for additional details and known issues.

Get started

To get started with ASP.NET Core in .NET Core 3.0 Preview 5 install the .NET Core 3.0 Preview 5 SDK. If you’re on Windows using Visual Studio, you also need to install the latest preview of Visual Studio.

Upgrade an existing project

To upgrade an existing an ASP.NET Core app (including Blazor apps) to .NET Core 3.0 Preview 5, follow the migrations steps in the ASP.NET Core docs. Please also see the full list of breaking changes in ASP.NET Core 3.0.

To upgrade an existing ASP.NET Core 3.0 Preview 4 project to Preview 5:

  • Update Microsoft.AspNetCore.* package references to 3.0.0-preview5-19227-01
  • Update Microsoft.Extensions.* package references to 3.0.0-preview5.19227.01

That’s it! You should be good to go with this latest preview release.

New JSON Serialization

In 3.0-preview5, ASP.NET Core MVC adds supports for reading and writing JSON using System.Text.Json. The System.Text.Json serializer can read and write JSON asynchronously, and is optimized for UTF-8 text making it ideal for REST APIs and backend applications.

This is available for you to try out in Preview 5, but is not yet the default in the templates. You can use the new serializer by removing the call to add Newtonsoft.Json formatters:

public void ConfigureServices(IServiceCollection services)
{ ... services.AddControllers() .AddNewtonsoftJson() ...
}

In the future this will be default for all new ASP.NET Core applications. We hope that you will try it in these earlier previews and log any issues you find here.

We used this WeatherForecast model when we profiled JSON read/writer performance using Newtonsoft.Json, our previous serializer.

public class WeatherForecast
{ public DateTime Date { get; set; } public int TemperatureC { get; set; } public string Summary { get; set; }
}

JSON deserialization (input)

Description RPS CPU (%) Memory (MB)
Newtonsoft.Json – 500 bytes 136,435 95 172
System.Text.Json – 500 bytes 167,861 94 169
Newtonsoft.Json – 2.4 kbytes 97,137 97 174
System.Text.Json – 2.4 kbytes 132,026 96 169
Newtonsoft.Json – 40 kbytes 7,712 88 212
System.Text.Json – 40 kbytes 16,625 96 193

JSON serialization (output)

Description RPS CPU (%) Memory (MB)
Newtonsoft.Json – 500 bytes 120,273 94 174
System.Text.Json – 500 bytes 145,631 94 173
Newtonsoft.Json – 8 Kbytes 35,408 98 187
System.Text.Json – 8 Kbytes 56,424 97 184
Newtonsoft.Json – 40 Kbytes 8,416 99 202
System.Text.Json – 40 Kbytes 14,848 98 197

For the most common payload sizes, System.Text.Json offers about 20% throughput increase during input and output formatting with a smaller memory footprint.

Options for the serializer can be configured using MvcOptions:

services.AddControllers(options => options.SerializerOptions.WriteIndented = true) 

Integration with SignalR

System.Text.Json is now the default Hub Protocol used by SignalR clients and servers starting in ASP.NET Core 3.0-preview5. Please try it out and file issues if you find anything not working as expected.

Switching back to Newtonsoft.Json

If you would like to switch back to the previous default of using Newtonsoft.Json then you can do so on both the client and server.

  1. Install the Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson NuGet package.
  2. On the client add .AddNewtonsoftJsonProtocol() to the HubConnectionBuilder:

    new HubConnectionBuilder()
    .WithUrl("/chatHub")
    .AddNewtonsoftJsonProtocol()
    .Build();
  3. On the server add .AddNewtonsoftJsonProtocol() to the AddSignalR() call:

    services.AddSignalR()
    .AddNewtonsoftJsonProtocol();

Give feedback

We hope you enjoy the new features in this preview release of ASP.NET Core! Please let us know what you think by filing issues on Github.

Avatar
Brady Gaster

Senior Program Manager, ASP.NET Core

Follow    

post

Azure SignalR Service now supports ASP.NET!

Avatar

Zhidi

We’ve just shipped the official version of the SignalR Service SDK for ASP.NET support:

Azure SignalR Service is a fully managed Azure service for real-time messaging. It is a preferred way for scaling ASP.NET Core SignalR application. However, SignalR Service is based on SignalR for ASP.NET Core 2.0, which is not 100% compatible with ASP.NET SignalR. Some code changes and proper version of dependent libraries are needed to make ASP.NET SignalR application work with SignalR Service.

We have received many usage feedbacks from customers since we announced the preview support for ASP.NET, at Microsoft Ignite 2018. Today, we are excited to announce that we have released the generally available version 1.0.0 of ASP.NET support SDK for Azure SignalR Service!

This diagram shows the typical architecture to use Azure SignalR Service with application server either written in ASP.NET Core, or now, in ASP.NET.

arch.png

For self-hosted SignalR application, the application server listens to and serves client connections directly. With SignalR Service, the application server will only respond to clients’ negotiate requests, and redirect clients to SignalR Service to establish the persistent client-server connections.

Using the ASP.NET support for Azure SignalR Service you will be able to:

  • Continue to keep SignalR application using ASP.NET, but work with fully managed ASP.NET Core based SignalR Service.
  • Change a few lines of SignalR API codes, to switch to use SignalR Service instead of self-hosted SignalR Hubs.
  • Leverage Azure SignalR Service’s built-in features and tools to help operate the SignalR application, with guaranteed SLA.

To receive the full benefit from the new ASP.NET support feature, please download and upgrade your SDKs to the latest supported versions:

  • .NET: 4.6.1+
  • Microsoft.AspNet.SignalR.*: 2.4.1
  • Microsoft.Azure.SignalR.AspNet: 1.0.0

Many factors, including non-technical ones, make the web application migrate from ASP.NET to ASP.NET Core difficult.

The ASP.NET support for Azure SignalR Service is to enable ASP.NET SignalR application developers to easily switch to use SignalR Service with minimal code change.

Some APIs and features are no longer supported:

  • Automatic reconnects
  • Forever Frame transport
  • HubState
  • PersistentConnection class
  • GlobalHost object
  • HubPipeline module
  • Client side Internet Explorer support before Microsoft Internet Explorer 11

ASP.NET support is focus on compatibility, so not all ASP.NET Core SignalR new features are supported. To name a few: MessagePack, Streaming, etc., are only available for ASP.NET Core SignalR applications.

SignalR Service can be configured for different service mode: Classic/Default/Serverless. For ASP.NET support, the Serverless mode is not supported.

For a complete list of feature comparison between ASP.NET SignalR and ASP.NET Core SignalR, the proper version of SDKs to use in each case, and what are the recommended alternatives to use for features discontinued in ASP.NET Core SignalR, please refer to doc here.

We’d like to hear about your feedback and comments. You can reach the product team at the GitHub repo, or by email.

Avatar
Zhidi Shang

Principal Program Manager, Azure SignalR Service

Follow Zhidi   

post

ASP.NET Core updates in .NET Core 3.0 Preview 4

Daniel Roth

Daniel

.NET Core 3.0 Preview 4 is now available and it includes a bunch of new updates to ASP.NET Core.

Here’s the list of what’s new in this preview:

  • Razor Components renamed back to server-side Blazor
  • Client-side Blazor on WebAssembly now in official preview
  • Resolve components based on @using
  • _Imports.razor
  • New component item template
  • Reconnection to the same server
  • Stateful reconnection after prerendering
  • Render stateful interactive components from Razor pages and views
  • Detect when the app is prerendering
  • Configure the SignalR client for server-side Blazor apps
  • Improved SignalR reconnect features
  • Configure SignalR client for server-side Blazor apps
  • Additional options for MVC service registration
  • Endpoint routing updates
  • New template for gRPC
  • Design-time build for gRPC
  • New Worker SDK

Please see the release notes for additional details and known issues.

Get started

To get started with ASP.NET Core in .NET Core 3.0 Preview 4 install the .NET Core 3.0 Preview 4 SDK

If you’re on Windows using Visual Studio, you also need to install the latest preview of Visual Studio 2019.

If you’re using Visual Studio Code, check out the improved Razor tooling and Blazor support in the C# extension.

Upgrade an existing project

To upgrade an existing an ASP.NET Core app to .NET Core 3.0 Preview 4, follow the migrations steps in the ASP.NET Core docs.

Please also see the full list of breaking changes in ASP.NET Core 3.0.

To upgrade an existing ASP.NET Core 3.0 Preview 3 project to Preview 4:

  • Update Microsoft.AspNetCore.* package references to 3.0.0-preview4-19216-03
  • In Razor Components apps (i.e. server-side Blazor apps) rename _ViewImports.cshtml to _Imports.razor for Razor imports that should apply to Razor components.
  • In Razor Component apps, in your Index.cshtml file, change the tag that references components.server.js so that it references blazor.server.js instead.
  • Remove any use of the _RazorComponentInclude property in your project file and rename and component files using the .cshtml file extension to use the .razor file extension instead.
  • Remove package references to Microsoft.AspNetCore.Components.Server.
  • Replace calls to AddRazorComponents in Startup.ConfigureServices with AddServerSideBlazor.
  • Replace calls to MapComponentHub with MapBlazorHub.
  • Remove any use of the Microsoft.AspNetCore.Components.Services namespace and replace with Microsoft.AspNetCore.Components as required.
  • In Razor Component apps, replace the {*clientPath} route in the host Razor Page with “/” and add a call to MapFallbackToPage in UseEndpoints.
  • Update any call to UseRouting in your Startup.Configure method to move the route mapping logic into a call to UseEndpoints at the point where you want the endpoints to be executed.

Before:

app.UseRouting(routes =>
{ routes.MapRazorPages();
}); app.UseCookiePolicy(); app.UseAuthorization();

After:

app.UseRouting(); app.UseCookiePolicy(); app.UseAuthorization(); app.UseEndpoints(routes =>
{ routes.MapRazorPages(); routes.MapFallbackToPage();
});

Razor Components renamed back to server-side Blazor

For a while, we’ve used the terminology Razor Components in some cases, and Blazor in other cases. This has proven to be confusing, so following a lot of community feedback, we’ve decided to drop the name ASP.NET Core Razor Components, and return to the name Server-side Blazor instead.

This emphasizes that Blazor is a single client app model with multiple hosting models:

  • Server-side Blazor runs on the server via SignalR
  • Client-side Blazor runs client-side on WebAssembly

… but either way, it’s the same programming model. The same Blazor components can be hosted in both environments.

In this preview of the .NET Core SDK we renamed the “Razor Components” template back to “Blazor (server-side)” and updated the related APIs accordingly. In Visual Studio the template will still show up as “Razor Components” when using Visual Studio 2019 16.1.0 Preview 1, but it will start showing up as “Blazor (server-side)” in a subsequent preview. We’ve also updated the template to use the new super cool flaming purple Blazor icon.

Blazor (server-side) template

Client-side Blazor on WebAssembly now in official preview

We’re also thrilled to announce that client-side Blazor on WebAssembly is now in official preview! Blazor is no longer experimental and we are committing to ship it as a supported web UI framework including support for running client-side in the browser on WebAssembly.

  • Server-side Blazor will ship as part of .NET Core 3.0. This was already announced last October.
  • Client-side Blazor won’t ship as part of the initial .NET Core 3.0 release, but we are now announcing it is committed to ship as part of a future .NET Core release (and hence is no longer an “experiment”).

With each preview release of .NET Core 3.0, we will continue to ship preview releases of both server and client-side Blazor.

Resolve components based on @using

Components in referenced assemblies are now always in scope and can be specified using their full type name including the namespace. You no longer need to import components from component libraries using the @addTagHelper directive.

For example, you can add a Counter component to the Index page like this:


Use the @using directive to bring component namespaces into scope just like you would in C# code:

@using BlazorWebApp1.Pages 

_Imports.razor

Use _Imports.razor files to import Razor directives across multiple Razor component files (.razor) in a hierarchical fashion.

For example, the following _Imports.razor file applies a layout and adds using statements for all Razor components in a the same folder and in any sub folders:

@layout MainLayout
@using Microsoft.AspNetCore.Components.
@using BlazorApp1.Data

This is similar to how you can use _ViewImports.cshtml with Razor views and pages, but applied specifically to Razor component files.

New component item template

You can now add components to Blazor apps using the new Razor Component item template:

dotnet new razorcomponent -n MyComponent1

Reconnection to the same server

Server-side Blazor apps require an active SignalR connection to the server to function. In this preview, the app will now attempt to reconnect to the server. As long as the state for that client is still in memory, the client session will resume without losing any state.

When the client detects that the connection has been lost a default UI is displayed to the user while the client attempts to reconnect:

Attempting reconnect

If reconnection failed the user is given the option to retry:

Reconnect failed

To customize this UI define an element with components-reconnect-modal as its ID. The client will update this element with one of the following CSS classes based on the state of the connection:

  • components-reconnect-show: Show the UI to indicate the connection was lost and the client is attempting to reconnect.
  • components-reconnect-hide: The client has an active connection – hide the UI.
  • components-reconnect-failed: Reconnection failed. To attempt reconnection again call window.Blazor.reconnect().

Stateful reconnection after prerendering

Server-side Blazor apps are setup by default to prerender the UI on the server before client connection back to the server is established. This is setup in the _Host.cshtml Razor page:

 @(await Html.RenderComponentAsync()) 
</body>

In this preview the client will now reconnect back to the server to the same state that was used to prerender the app. If the app state is still in memory it doesn’t need to be rerendered once the SignalR connection is established.

Render stateful interactive components from Razor pages and views

You can now add stateful interactive components to a Razor page or View. When the page or view renders the component will be prerendered with it. The app will then reconnect to the component state once the client connection has been established as long as it is still in memory.

For example, the following Razor page renders a Counter component with an initial count that is specified using a form:

<h1>My Razor Page</h1>
<form> <input type="number" asp-for="InitialCount" /> <button type="submit">Set initial count</button>
</form> @(await Html.RenderComponentAsync<Counter>(new { InitialCount = InitialCount })) @functions { [BindProperty(SupportsGet=true)] public int InitialCount { get; set; }
}

Interactive component on Razor page

Detect when the app is prerendering

While a Blazor app is prerendering, certain actions (like calling into JavaScript) are not possible because a connection with the browser has not yet been established. Components may need to render differently when being prerendered.

To delay JavaScript interop calls until after the connection with the browser has been established you can now use the OnAfterRenderAsync component lifecycle event. This event will only be called after the app has been fully rendered and the client connection established.

To conditionally render different content based on whether the app is currently being prerendered or not use IsConnected property on the IComponentContext service. This property will only return true if there is an active connection with the client.

Configure the SignalR client for server-side Blazor apps

Sometimes you need to configure the SignalR client used by server-side Blazor apps. For example, you might want to configure logging on the SignalR client to diagnose a connection issue.

To configure the SignalR client for server-side Blazor apps, add an autostart="false" attribute on the script tag for the blazor.server.js script, and then call Blazor.start passing in a config object that specifies the SignalR builder:

http://_framework/blazor.server.js
 Blazor.start({ configureSignalR: function (builder) { builder.configureLogging(2); // LogLevel.Information } });

Improved SignalR connection lifetime handling

Preview 4 will improve the developer experience for handling SignalR disconnection and reconnection. Automatic reconnects can be enabled by calling the withAutomaticReconnect method on HubConnectionBuilder:

const connection = new signalR.HubConnectionBuilder() .withUrl("/chatHub") .withAutomaticReconnect() .build();

Without any parameters, withAutomaticReconnect() will cause the configure the client to try to reconnect, waiting 0, 2, 10 and 30 seconds respectively before between each attempt.

In order to configure a non-default number of reconnect attempts before failure, or to change the reconnect timing, withAutomaticReconnect accepts an array of numbers representing the delay in milliseconds to wait before starting each reconnect attempt.

const connection = new signalR.HubConnectionBuilder() .withUrl("/chatHub") .withAutomaticReconnect([0, 0, 2000, 5000]) // defaults to [0, 2000, 10000, 30000] .build();

Improved disconnect & reconnect handling opportunities

Before starting any reconnect attempts, the HubConnection will transition to the Reconnecting state and fire its onreconnecting callback. This provides an opportunity to warn users that the connection has been lost, disable UI elements, and mitigate confusing user scenarios that might occur due to the disconnected state.

connection.onreconnecting((error) => { console.assert(connection.state === signalR.HubConnectionState.Reconnecting); document.getElementById("messageInput").disabled = true; const li = document.createElement("li"); li.textContent = `Connection lost due to error "${error}". Reconnecting.`; document.getElementById("messagesList").appendChild(li);
});

If the client successfully reconnects within its first four attempts, the HubConnection will transition back to the Connected state and fire onreconnected callbacks. This gives developers a good opportunity to inform users the connection has been reestablished.

connection.onreconnected((connectionId) => { console.assert(connection.state === signalR.HubConnectionState.Connected); document.getElementById("messageInput").disabled = false; const li = document.createElement("li"); li.textContent = `Connection reestablished. Connected with connectionId "${connectionId}".`; document.getElementById("messagesList").appendChild(li);
});

If the client doesn’t successfully reconnect within its first four attempts, the HubConnection will transition to the Disconnected state and fire its onclosed callbacks. This is a good opportunity to inform users the connection has been permanently lost and recommend refreshing the page.

connection.onclose((error) => { console.assert(connection.state === signalR.HubConnectionState.Disconnected); document.getElementById("messageInput").disabled = true; const li = document.createElement("li"); li.textContent = `Connection closed due to error "${error}". Try refreshing this page to restart the connection.`; document.getElementById("messagesList").appendChild(li);
})

Additional options for MVC service registration

We’re adding some new options for registering MVC’s various features inside ConfigureServices.

What’s changing

We’re adding three new top level extension methods related to MVC features on IServiceCollection. Along with this change we are updating our templates to use these new methods instead of AddMvc().

AddMvc() is not being removed and will continue to behave as it does today.

public void ConfigureServices(IServiceCollection services)
{ // Adds support for controllers and API-related features - but not views or pages. // // Used by the API template. services.AddControllers();
}
public void ConfigureServices(IServiceCollection services)
{ // Adds support for controllers, API-related features, and views - but not pages. // // Used by the Web Application (MVC) template. services.AddControllersWithViews();
}
public void ConfigureServices(IServiceCollection services)
{ // Adds support for Razor Pages and minimal controller support. // // Used by the Web Application template. services.AddRazorPages();
}

These new methods can also be combined. This example is equivalent to the current AddMvc().

public void ConfigureServices(IServiceCollection services)
{ services.AddControllers(); services.AddRazorPages();
}

These methods return an IMvcBuilder that can be chained to access any of the methods that are available today from the builder returned by AddMvc().

We recommend using whichever option feels best based on your needs.

Motivations

We wanted to provide some more options that represent how users use the product. In particular we’ve received strong feedback from users that want an API-focused flavor of MVC without the overhead for having the ability to serve views and pages. We tried to provide an experience for this in the past through the AddMvcCore() method, but that approach hasn’t been very successful. Users who tried using AddMvcCore() have been surprised by how much they need to know to use it successfully, and as a result we haven’t promoted its usage. We hope that AddControllers() will better satisfy this scenario.

In addition to the AddControllers() experience, we’re also attempting to create options that feel right for other scenarios. We’ve heard requests for this in the past, but not as strongly as the requests for an API-focused profile. Your feedback about whether AddMvc() could be improved upon, and how will be valuable.

What’s in AddControllers()

AddControllers() includes support for:

  • Controllers
  • Model Binding
  • API Explorer (OpenAPI integration)
  • Authorization [Authorize]
  • CORS [EnableCors]
  • Data Annotations validation [Required]
  • Formatter Mappings (translate a file-extension to a content-type)

All of these features are included because they fit under the API-focused banner, and they are very much pay-for-play. None of these features proactively interact with the request pipeline, these are activated by attributes on your controller or model class. API Explorer is an slight exception, it is a piece of infrastructure used by OpenAPI libraries and will do nothing without Swashbuckle or NSwag.

Some notable features AddMvc() includes but AddControllers() does not:

  • Antiforgery
  • Temp Data
  • Views
  • Pages
  • Tag Helpers
  • Memory Cache

These features are view-related and aren’t necessary in an API-focused profile of MVC.

What’s in AddControllersWithViews()

AddControllersWithViews() includes support for:

  • Controllers
  • Model Binding
  • API Explorer (OpenAPI integration)
  • Authorization [Authorize]
  • CORS [EnableCors]
  • Data Annotations validation [Required]
  • Formatter Mappings (translate a file-extension to a content-type)
  • Antiforgery
  • Temp Data
  • Views
  • Tag Helpers
  • Memory Cache

We wanted to position AddControllersWithViews() as a superset of AddControllers() for simplicity in explaining it. This features set also happens to align with the ASP.NET Core 1.X release (before Razor Pages).

Some notable features AddMvc() includes but AddControllersWithViews() does not:
– Pages

What’s in AddRazorPages()

AddRazorPages() includes support for:

  • Pages
  • Controllers
  • Model Binding
  • Authorization [Authorize]
  • Data Annotations validation [Required]
  • Antiforgery
  • Temp Data
  • Views
  • Tag Helpers
  • Memory Cache

For now this profile includes basic support for controllers, but excludes many of the API-focused features listed below. We’re interested in your feedback about what should be included by default in AddRazorPages().

Some notable features AddMvc() includes but AddRazorPages() does not:

  • API Explorer (OpenAPI integration)
  • CORS [EnableCors]
  • Formatter Mappings (translate a file-extension to a content-type)

Endpoint Routing updates

In ASP.NET Core 2.2 we introduced a new routing implementation called Endpoint Routing which replaces IRouter-based routing for ASP.NET Core MVC. In the upcoming 3.0 release Endpoint Routing will become central to the ASP.NET Core middleware programming model. Endpoint Routing is designed to support greater interoperability between frameworks that need routing (MVC, gRPC, SignalR, and more …) and middleware that want to understand the decisions made by routing (localization, authorization, CORS, and more …).

While it’s still possible to use the old UseMvc() or UseRouter() middleware in a 3.0 application, we recommend that every application migrate to Endpoint Routing if possible. We are taking steps to address compatibility bugs and fill in previously unsupported scenarios. We welcome your feedback about what features are missing or anything else that’s not great about routing in this preview release.

We’ll be uploading another post soon with a conceptual overview and cookbook for Endpoint Routing in 3.0.

Endpoint Routing overview

Endpoint Routing is made up of the pair of middleware created by app.UseRouting() and app.UseEndpoints(). app.UseRouting() marks the position in the middleware pipeline where a routing decision is made – where an endpoint is selected. app.UseEndpoints() marks the position in the middleware pipeline where the selected endpoint is executed. Middleware that run in between these can see the selected endpoint (if any) or can select a different endpoint.

If you’re familiar with routing from using MVC then most of what you have experienced so far will behave the same way. Endpoint Routing understands the same route template syntax and processes URLs in a very similar way to the in-the-box implementations of IRouter. Endpoint routing supports the [Route] and similar attributes inside MVC.

We expect most applications will only require changes to the Startup.cs file.

A typical Configure() method using Endpoint Routing has the following high-level structure:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{ // Middleware that run before routing. Usually the following appear here: if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); } else { app.UseExceptionHandler("/Error"); } app.UseStaticFiles() // Runs matching. An endpoint is selected and set on the HttpContext if a match is found. app.UseRouting(); // Middleware that run after routing occurs. Usually the following appear here: app.UseAuthentication() app.UseAuthorization() app.UseCors() // These middleware can take different actions based on the endpoint. // Executes the endpoint that was selected by routing. app.UseEndpoints(endpoints => { // Mapping of endpoints goes here: endpoints.MapControllers() endpoints.MapRazorPages() endpoints.MapHub<MyChatHub>() endpoints.MapGrpcService<MyCalculatorService>() }); // Middleware here will only run if nothing was matched.
}

MVC Controllers, Razor Pages, SignalR, gRPC, and more are added inside UseEndpoints() – they are now part of the same routing system.

New template for gRPC

The gRPC template has been simplified to a single project template. We no longer include a gRPC client as part of the template.
For instructions on how to create a gRPC client, refer to the docs.

.
├── appsettings.Development.json
├── appsettings.json
├── grpc.csproj
├── Program.cs
├── Properties
│   └── launchSettings.json
├── Protos
│   └── greet.proto
├── Services
│   └── GreeterService.cs
└── Startup.cs 3 directories, 8 files

Design-time build for gRPC

Design-time build support for gRPC code-generation makes it easier to rapidly iterate on your gRPC services. Changes to your *.proto files no longer require you to build your project to re-run code generation.

Design time build

Worker SDK

In Preview 3 we introduced the new Worker Service template. In Preview 4 we’ve further decoupled that template from Web by introducing its own SDK. If you create a new Worker Service your csproj will now look like the following:

<Project Sdk="Microsoft.NET.Sdk.Worker"> <PropertyGroup> <TargetFramework>netcoreapp3.0</TargetFramework> <UserSecretsId>dotnet-WebApplication59-A2B1DB8D-0408-4583-80BA-1B32DAE36B97</UserSecretsId> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0-preview4.19216.2" /> </ItemGroup>
</Project>

We’ll have more to share on the new Worker SDK in a future post.

Give feedback

We hope you enjoy the new features in this preview release of ASP.NET Core! Please let us know what you think by filing issues on GitHub.

Daniel Roth
Daniel Roth

Principal Program Manager, ASP.NET

Follow Daniel   

post

Blazor now in official preview!

Daniel Roth

Daniel

With this newest Blazor release we’re pleased to announce that Blazor is now in official preview! Blazor is no longer experimental and we are committing to ship it as a supported web UI framework including support for running client-side in the browser on WebAssembly.

A little over a year ago we started the Blazor experimental project with the goal of building a client web UI framework based on .NET and WebAssembly. At the time Blazor was little more than a prototype and there were lots of open questions about the viability of running .NET in the browser. Since then we’ve shipped nine experimental Blazor releases addressing a variety of concerns including component model, data binding, event handling, routing, layouts, app size, hosting models, debugging, and tooling. We’re now at the point where we think Blazor is ready to take its next step.

Blazor icon

Simplifying the naming and versioning

For a while, we’ve used the terminology Razor Components in some cases, and Blazor in other cases. This has proven to be confusing, so following a lot of community feedback, we’ve decided to drop the name ASP.NET Core Razor Components, and return to the name Server-side Blazor instead.

This emphasizes that Blazor is a single client app model with multiple hosting models:

  • Server-side Blazor runs on the server via SignalR
  • Client-side Blazor runs client-side on WebAssembly

… but either way, it’s the same programming model. The same Blazor components can be hosted in both environments.

Also, since Blazor is now part of .NET Core, the client-side Blazor package versions now align with the .NET Core 3.0 versions. For example, the version number of all the preview packages we are shipping today is 3.0.0-preview4-19216-03. We no longer use separate 0.x version numbers for client-side Blazor packages.

What will ship when

  • Server-side Blazor will ship as part of .NET Core 3.0. This was already announced last October.
  • Client-side Blazor won’t ship as part of the initial .NET Core 3.0 release, but we are now announcing it is committed to ship as part of a future .NET Core release (and hence is no longer an “experiment”).

With each preview release of .NET Core 3.0, we will continue to ship preview releases of both server and client-side Blazor.

Today’s preview release

New features in this preview release:

  • Templates updated to use the .razor file extension
  • _Imports.razor
  • Scope components with @using
  • New component item template
  • New Blazor icons
  • Blazor support in Visual Studio Code

Check out the ASP.NET Core 3.0 Preview 4 announcement for details on these improvements. See also the Blazor release notes for additional details on this preview release.

Get the Blazor preview

To get started with the Blazor preview install the following:

  1. .NET Core 3.0 Preview 4 SDK (3.0.100-preview4-011223)
  2. The Blazor templates on the command-line:

    dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.0.0-preview4-19216-03
    
  3. Visual Studio 2019 Preview with the ASP.NET and web development workload selected as well as the latest Blazor extension from the Visual Studio Marketplace, or Visual Studio Code with the latest C# extension (now with Blazor support!).

You can find getting started instructions, docs, and tutorials for Blazor at our new Blazor home page at https://blazor.net.

Blazor home page

Upgrade to the Blazor preview:

To upgrade your existing Blazor apps to the new Blazor preview first make sure you’ve installed the prerequisites listed above then follow these steps:

  • Update all Microsoft.AspNetCore.Blazor.* package references to 3.0.0-preview4-19216-03.
  • Remove any package reference to Microsoft.AspNetCore.Components.Server.
  • Remove any DotNetCliToolReference to Microsoft.AspNetCore.Blazor.Cli and replace with a package reference to Microsoft.AspNetCore.Blazor.DevServer.
  • In client Blazor projects remove the <RunCommand>dotnet</RunCommand> and <RunArguments>blazor serve</RunArguments> properties.
  • In client Blazor projects add the <RazorLangVersion>3.0</RazorLangVersion> property.
  • Rename all _ViewImports.cshtml files to _Imports.razor.
  • Rename all remaining .cshtml files to .razor.
  • Rename components.webassembly.js to blazor.webassembly.js
  • Remove any use of the Microsoft.AspNetCore.Components.Services namespace and replace with Microsoft.AspNetCore.Components as required.
  • Update server projects to use endpoint routing:
// Replace this:
app.UseMvc(routes =>
{ routes.MapRoute(name: "default", template: "{controller}/{action}/{id?}");
}); // With this:
app.UseRouting(); app.UseEndpoints(routes =>
{ routes.MapDefaultControllerRoute();
});
  • Run dotnet clean on the solution to clear out old Razor declarations.

Blazor community page is now Awesome Blazor

As part of updating the Blazor site, we’ve decided to retire the Blazor community page and instead direct folks to the community driven Awesome Blazor site. Thank you Adrien Torris for maintaining this truly “awesome” list of Blazor resources!

Try out preview Blazor UI offerings from Telerik, DevExpress, and Syncfusion

Blazor benefits from an active and supportive community that has contributed all sorts of sample apps, components, and libraries to the Blazor ecosystem. Recently popular component vendors like Telerik, DevExpress, and Syncfusion have joined in the fun and shipped previews of Blazor UI components. We encourage you to give these Blazor UI offerings a try and let them know what you think.

Give feedback

We hope you enjoy this latest preview release of Blazor. As with previous releases, your feedback is important to us. If you run into issues or have questions while trying out Blazor, file issues on GitHub. You can also chat with us and the Blazor community on Gitter if you get stuck or to share how Blazor is working for you. After you’ve tried out Blazor for a while please let us know what you think by taking our in-product survey. Click the survey link shown on the app home page when running one of the Blazor project templates:

Blazor survey

Thanks for trying out Blazor!

Daniel Roth
Daniel Roth

Principal Program Manager, ASP.NET

Follow Daniel   

post

Updated Razor support in Visual Studio Code, now with Blazor support

Daniel Roth

Daniel

Today we are pleased to announce improved Razor tooling support in Visual Studio Code with the latest C# extension. This latest release includes improved Razor diagnostics and support for tag helpers and Blazor apps.

Get Started

To use this preview of Razor support in Visual Studio Code install the following:

To try out Visual Studio Code with Blazor apps, also install:

  • .NET Core 3.0 (Preview 4 or later)
  • The latest Blazor CLI templates:

    dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.0.0-preview4-19216-03
    

What’s new in this release?

Improved diagnostics

We’ve improved the Razor diagnostics in Visual Studio Code for a variety of scenarios, including floating @ characters:

Floating @ character

Missing end braces:

Missing end brace

And missing end tags in code blocks:

Missing end tag

Tag helpers

Tag helper completions are now supported in ASP.NET Core projects:

Tag helper completion

As well as completions for tag helper attribute names and values:

Tag helper attribute completion

Blazor

Visual Studio Code now works with Blazor apps too!

You get completions for components and component parameters:

Component completions

Also data-binding, event handlers and lots of other Blazor goodies!

Blazor todos

Limitations and known issues

This is an alpha release of the Razor tooling for Visual Studio Code, so there are a number of limitations and known issues:

  • Razor editing is currently only supported in ASP.NET Core and Blazor projects (no support for ASP.NET projects)
  • Limited support for colorization

Note that if you need to disable the Razor tooling:

  • Open the Visual Studio Code User Settings: File -> Preferences -> Settings
  • Search for “razor”
  • Check the “Razor: Disabled” checkbox

Feedback

Please let us know what you think about this latest update to the Razor tooling support in Visual Studio Code by reporting issues in the Razor.VSCode repo. When reporting Razor tooling related issues please use the “Report a Razor Issue” command in Visual Studio Code to capture all of the relevant longs and diagnostic information. Just run the command and then follow the instructions.

Thanks for trying out Razor in Visual Studio Code!

Daniel Roth
Daniel Roth

Principal Program Manager, ASP.NET

Follow Daniel   

post

.NET Core Workers in Azure Container Instances

Avatar

In .NET Core 3.0 we are introducing a new type of application template called Worker Service. This template is intended to give you a starting point for writing long running services in .NET Core. In this walkthrough you’ll learn how to use a Worker with Azure Container Registry and Azure Container Instances to get your Worker running as a microservice in the cloud.

Since the Worker template Glenn blogged about is also available via the dotnet new command line, I can create one on my Mac and edit the code using Visual Studio for Mac or Visual Studio Code (which I’ll be using here to take advantage of the integrated Docker extension).

dotnet new worker

I’ll use the default from the Worker template. As it will write to logs during execution via ILogger, I’ll be able to tell quickly from looking in the logs if the Worker is running.

public class Worker : BackgroundService
{ private readonly ILogger<Worker> _logger; public Worker(ILogger<Worker> logger) { _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); await Task.Delay(1000, stoppingToken); } }
}

Visual Studio Code’s Docker tools are intelligent enough to figure out this is a .NET Core app, and will suggest the correct Docker file via the Command Palette’s Add Docker files to workspace option.

By right-clicking the resulting Dockerfile I can build the Worker into a Docker image in one click.

The Build Image option will package my Worker’s code into a Docker container locally. The second option, ACR Tasks: Build Image would use Azure Container Registry Tasks to build the image in the cloud, rather than on disk. This is helpful for scenarios when the base image is larger than I want to download locally or when I’m building an application on a Windows base image from Linux or Mac. You can learn more about ACR Tasks in the ACR docs. The Azure CLI makes it easy to login to the Azure Container Registry using the Azure CLI. This results in my Docker client being authenticated to the Azure Container Registry in my subscription.

az acr login -n BackgroundWorkerImages

This can be done in the VS Code integrated terminal or in the local terminal, as the setting will be persisted across the terminals’ environment. It can’t be done using the cloud shell, since logging into the Azure Container Registry requires local shell access so local Docker images can be accessed. Before I push the container image into my registry, I need to tag the image with the URI of the image once it has been pushed into my registry. I can easily get the ACR instance URI from the portal.

I’ll copy the URI of the registry’s login server in the portal so I can paste it when I tag the image later.

By selecting the backgroundworker:latest image in Visual Studio Code’s Docker explorer pane, I can select Tag Image.

I’ll be prompted for the tag, and I can easily paste in the URI I copied from the portal.

Finally, I can right-click the image tag I created and select Push, and the image will be pushed into the registry. Once I have a Docker image in the registry, I can use the CLI or tools to deploy it to Azure Container Instances, Kubernetes, or even Azure App Service.

Now that the worker is containerized and stored in the registry, starting an instance of it is one click away.

Once the container instance starts up, I’ll see some logs indicating the worker is executing, but these are just the basic startup logs and not my information-level logs I have in my Worker code.

Since I added Information-level logs during the worker’s execution, the configuration in appsettings.json (or the environment variable for the container instance) will need to be updated to see more verbose logs.

{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.Hosting.Lifetime": "Information" } }
}

Once the code is re-packaged into an updated Docker image and pushed into the Azure Container Registry, following a simple Restart…

… more details will be visible in the container instance’s logging output.

The Worker template makes it easy to create long-running background workers that you can run for as long as you need in Azure Container Instances. New container instances can be created using the portal or the Azure Command Line. Or, you can opt for more advanced scenarios using Azure DevOps or Logic Apps. With the Worker template making it easy to get started building microservices using your favorite ASP.NET Core idioms and Azure’s arsenal of container orchestration services you can get your microservices up and running in minutes.

Avatar
Brady Gaster

Senior Program Manager, ASP.NET Core

Follow    

<!–


–>

post

.NET Core Workers as Windows Services

Avatar

Glenn

In .NET Core 3.0 we are introducing a new type of application template called Worker Service. This template is intended to give you a starting point for writing long running services in .NET Core. In this walkthrough we will create a worker and run it as a Windows Service.

Create a worker

Preview Note: In our preview releases the worker template is in the same menu as the Web templates. This will change in a future release. We intend to place the Worker Server template directly inside the create new project wizard.

Create a Worker in Visual Studio

image

image

image

Create a Worker on the command line

Run dotnet new worker

image

Run as a Windows Service

In order to run as a Windows Service we need our worker to listen for start and stop signals from ServiceBase the .NET type that exposes the Windows Service systems to .NET applications. To do this we want to:

Add the Microsoft.Extensions.Hosting.WindowsServices NuGet package

image

Add the UseServiceBaseLifetime call to the HostBuilder in our Program.cs

public class Program
{ public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseServiceBaseLifetime() .ConfigureServices(services => { services.AddHostedService<Worker>(); });
}

This method does a couple of things. First, it checks whether or not the application is actually running as a Windows Service, if it isn’t then it noops which makes this method safe to be called when running locally or when running as a Windows Service. You don’t need to add guard clauses to it and can just run the app normally when not installed as a Windows Service.

Secondly, it configures your host to use a ServiceBaseLifetime. ServiceBaseLifetime works with ServiceBase to help control the lifetime of your app when run as a Windows Service. This overrides the default ConsoleLifetime that handles signals like CTL+C.

Install the Worker

Once we have our worker using the ServiceBaseLifetime we then need to install it:

First, lets publish the application. We will install the Windows Service in-place, meaning the exe will be locked whenever the service is running. The publish step is a nice way to make sure all the files I need to run the service are in one place and ready to be installed.

dotnet publish -o c:\code\workerpub

Then we can use the sc utility in an admin command prompt

sc create workertest binPath=c:\code\workerpub\WorkerTest.exe

For example:

image

Security note: This command has the service run as local system, which isn’t something you will generally want to do. Instead you should create a service account and run the windows service as that account. We will not talk about that here, but there is some documentation on the ASP.NET docs talking about it here: https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/windows-service?view=aspnetcore-2.2

Logging

The logging system has an Event Log provider that can send log message directly to the Windows Event Log. To log to the event log you can add the Microsoft.Extensions.Logging.EventLog package and then modify your Program.cs:

public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureLogging(loggerFactory => loggerFactory.AddEventLog()) .ConfigureServices(services => { services.AddHostedService<Worker>(); });

In upcoming previews we plan to improve the experience of using Workers with Windows Services by:

  1. Rename UseWindowsServiceBaseLifetime to UseWindowsService
  2. Add automatic and improved integration with the Event Log when running as a Windows Service.

We hope you try out this new template and want you to let us know how it goes, you can file any bugs or suggestions here: https://github.com/aspnet/AspNetCore/issues/new/choose

Avatar

post

Blazor 0.9.0 experimental release now available

Daniel Roth

Daniel

Blazor 0.9.0 is now available! This release updates Blazor with the Razor Components improvements in .NET Core 3.0 Preview 3.

New Razor Component improvements now available to Blazor apps:

  • Improved event handling
  • Forms & validation

Checkout the ASP.NET Core 3.0 Preview 3 announcement for details on these improvements. See also the Blazor 0.9.0 release notes for additional details.

Note: The Blazor templates have not been updated to use the new .razor file extension for Razor Components in this release. This update will be done in a future release.

Get Blazor 0.9.0

To get started with Blazor 0.9.0 install the following:

  1. .NET Core 3.0 Preview 3 SDK (3.0.100-preview3-010431)
  2. Visual Studio 2019 (Preview 4 or later) with the ASP.NET and web development workload selected.
  3. The latest Blazor extension from the Visual Studio Marketplace.
  4. The Blazor templates on the command-line:

    dotnet new -i Microsoft.AspNetCore.Blazor.Templates::0.9.0-preview3-19154-02
    

You can find getting started instructions, docs, and tutorials for Blazor at https://blazor.net.

Upgrade to Blazor 0.9.0

To upgrade your existing Blazor apps to Blazor 0.9.0 first make sure you’ve installed the prerequisites listed above.

To upgrade a Blazor 0.8.0 project to 0.9.0:

  • Update the Blazor packages and .NET CLI tool references to 0.9.0-preview3-19154-02.
  • Update the remaining Microsoft.AspNetCore.* packages to 3.0.0-preview3-19153-02.
  • Remove any usage of JSRuntime.Current and instead use dependency injection to get the current IJSRuntime instance and pass it through to where it is needed.

Give feedback

We hope you enjoy this latest preview release of Blazor. As with previous releases, your feedback is important to us. If you run into issues or have questions while trying out Blazor, file issues on GitHub. You can also chat with us and the Blazor community on Gitter if you get stuck or to share how Blazor is working for you. After you’ve tried out Blazor for a while please let us know what you think by taking our in-product survey. Click the survey link shown on the app home page when running one of the Blazor project templates:

Blazor survey

Thanks for trying out Blazor!

Daniel Roth
Daniel Roth

Principal Program Manager, ASP.NET

Follow Daniel   

<!–


–>

post

ASP.NET Core updates in .NET Core 3.0 Preview 3

Daniel Roth

Daniel

.NET Core 3.0 Preview 3 is now available and it includes a bunch of new updates to ASP.NET Core.

Here’s the list of what’s new in this preview:

  • Razor Components improvements:
    • Single project template
    • New .razor extension
    • Endpoint routing integration
    • Prerendering
    • Razor Components in Razor Class Libraries
    • Improved event handling
    • Forms & validation
  • Runtime compilation
  • Worker Service template
  • gRPC template
  • Angular template updated to Angular 7
  • Authentication for Single Page Applications
  • SignalR integration with endpoint routing
  • SignalR Java client support for long polling

Please see the release notes for additional details and known issues.

Get started

To get started with ASP.NET Core in .NET Core 3.0 Preview 3 install the .NET Core 3.0 Preview 3 SDK

If you’re on Windows using Visual Studio, you’ll also want to install the latest preview of Visual Studio 2019.

  • Note: To use use this preview of .NET Core 3.0 with the release channel of Visual Studio 2019, you will need to enable the option to use previews of the .NET Core SDK by going to Tools > Options > Projects and Solutions > .NET Core > Use previews of the .NET Core SDK

Upgrade an existing project

To upgrade an existing an ASP.NET Core app to .NET Core 3.0 Preview 3, follow the migrations steps in the ASP.NET Core docs.

Please also see the full list of breaking changes in ASP.NET Core 3.0.

Razor Components improvements

In the previous preview, we introduced Razor Components as a new way to build interactive client-side web UI with ASP.NET Core. This section covers the various improvements we’ve made to Razor Components in this preview update.

Single project template

The Razor Components project template is now a single project instead of two projects in the same solution. The authored Razor Components live directly in the ASP.NET Core app that hosts them. The same ASP.NET Core project can contain Razor Components, Pages, and Views. The Razor Components template also has HTTPS enabled by default like the other ASP.NET Core web app templates.

New .razor extension

Razor Components are authored using Razor syntax, but are compiled differently than Razor Pages and Views. To clarify which Razor files should be compiled as Razor Components we’ve introduced a new file extension: .razor. In the Razor Components template all component files now use the .razor extension. Razor Pages and Views still use the .cshtml extension.

Razor Components can still be authored using the .cshtml file extension as long as those files are identified as Razor Component files using the _RazorComponentInclude MSBuild property. For example, the Razor Component template in this release specifies that all .cshtml files under the Components folder should be treated as Razor Components.

<_RazorComponentInclude>Components\**\*.cshtml</_RazorComponentInclude>

Please note that there are a number of limitations with .razor files in this release. Please refer to the release notes for the list of known issues and available workarounds.

Endpoint routing integration

Razor Components are now integrated into ASP.NET Core’s new Endpoint Routing system. To enable Razor Components support in your application, use MapComponentHub<TComponent> within your routing configuration. For example,

app.UseRouting(routes =>
{ routes.MapRazorPages(); routes.MapComponentHub<App>("app");
});

This configures the application to accept incoming connections for interactive Razor Components, and specifies that the root component App should be rendered within a DOM element matching the selector app.

Prerendering

The Razor Components project template now does server-side prerendering by default. This means that when a user navigates to your application, the server will perform an initial render of your Razor Components and deliver the result to their browser as plain static HTML. Then, the browser will reconnect to the server via SignalR and switch the Razor Components into a fully interactive mode. This two-phase delivery is beneficial because:

  • It improves the perceived performance of the site, because the UI can appear sooner, without waiting to make any WebSocket connections or even running any client-side script. This makes a bigger difference for users on slow connections, such as 2G/3G mobiles.
  • It can make your application easily crawlable by search engines.

For users on faster connections, such as intranet users, this feature has less impact because the UI should appear near-instantly regardless.

To set up prerendering, the Razor Components project template no longer has a static HTML file. Instead a single Razor Page, /Pages/Index.cshtml, is used to prerender the app content using the Html.RenderComponentAsync<TComponent>() HTML helper. The page also references the components.server.js script to set up the SignalR connection after the content has been prerendered and downloaded. And because this is a Razor Page, features like the environment tag helper just work.

Index.cshtml

@page "{*clientPath}"
<!DOCTYPE html>
<html>
<head> ...
</head>
<body> <app>@(await Html.RenderComponentAsync<App>())</app> http://_framework/components.server.js
</body>
</html>

Besides the app loading faster, you can see that prerendering is happening by looking at the downloaded HTML source in the browser dev tools. The Razor Components are fully rendered in the HTML.

Razor Components in Razor Class Libraries

You can now add Razor Components to Razor Class Libraries and reference them from ASP.NET Core projects using Razor Components.

To create reusable Razor Components in a Razor Class Library:

  1. Create an Razor Components app:

    dotnet new razorcomponents -o RazorComponentsApp1
    
  2. Create a new Razor Class Library

    dotnet new razorclasslib -o RazorClassLib1
    
  3. Add a Component1.razor file to the Razor Class Library

Component1.razor

<h1>Component1</h1> <p>@message</p> @functions { string message = "Hello from a Razor Class Library"!;
}
  1. Reference the Razor Class Library from an ASP.NET Core app using Razor Components:

    dotnet add RazorComponentsApp1 reference RazorClassLib1
    
  2. In the Razor Components app, import all components from the Razor Class Library using the @addTagHelper directive and then use Component1 in the app:

Index.razor

@page "/"
@addTagHelper *, RazorClassLib1 <h1>Hello, world!</h1> Welcome to your new app. <Component1 />

Note that Razor Class Libraries are not compatible with Blazor apps in this release. Also, Razor Class Libraries do not yet support static assets. To create components in a library that can be shared with Blazor and Razor Components apps you still need to use a Blazor Class Library. This is something we expect to address in a future update.

Improved event handling

The new EventCallback and EventCallback<> types make defining component callbacks much more straightforward. For example consider the following two components:

MyButton.razor

<button onclick="@OnClick">Click here and see what happens!</button> @functions { [Parameter] EventCallback<UIMouseEventArgs> OnClick { get; set; }
}

UsesMyButton.razor

@text
<MyButton OnClick="ShowMessage" /> @function { string text; void ShowMessage(UIMouseEventArgs e) { text = "Hello, world!"; } }

The OnClick callback is of type EventCallback<UIMouseEventArgs> (instead of Action<UIMouseEventArgs>), which MyButton passes off directly to the onclick event handler. The compiler handles converting the delegate to an EventCallback, and will do some other things to make sure that the rendering process has enough information to render the correct target component. As a result an explicit call to StateHasChanged in the ShowMessage event handler isn’t necessary.

By using the EventCallback<> type OnClick handler can now also be asynchronous without any additional code changes to MyButton:

UsesMyButton.razor

@text
<MyButton OnClick="ShowMessageAsync" /> @function { string text; async Task ShowMessageAsync(UIMouseEventArgs e) { await Task.Yield(); text = "Hello, world!"; } }

We recommend using EventCallback and EventCallback<T> when you define component parameters for event handling and binding. Use EventCallback<> where possible because it’s strongly typed and will provide better feedback to users of your component. Use EventCallback when there’s no value you will pass to the callback.

Note that consumers don’t have to write different code when using a component because of EventCallback. The same event handling code should still work, while removing some thorny issues and improving the usability of your components.

Forms & validation

This preview release adds built-in components and infrastructure for handling forms and validation.

One of the benefits of using .NET for client-side web development is the ability to share the same implementation logic between the client and the server. Validation logic is a prime example. The new forms & validation support in Razor Components includes support for handling validation using data annotations, or you can plug in your preferred validation system.

For example, the following Person type defines validation logic using data annotations:

public class Person
{ [Required(ErrorMessage = "Enter a name")] [StringLength(10, ErrorMessage = "That name is too long")] public string Name { get; set; } [Range(0, 200, ErrorMessage = "Nobody is that old")] public int AgeInYears { get; set; } [Required] [Range(typeof(bool), "true", "true", ErrorMessage = "Must accept terms")] public bool AcceptsTerms { get; set; }
}

Here’s how you can create a validating form based on this Person model:

<EditForm Model="@person" OnValidSubmit="@HandleValidSubmit"> <DataAnnotationsValidator /> <ValidationSummary /> <p class="name"> Name: <InputText bind-Value="@person.Name" /> </p> <p class="age"> Age (years): <InputNumber bind-Value="@person.AgeInYears" /> </p> <p class="accepts-terms"> Accepts terms: <InputCheckbox bind-Value="@person.AcceptsTerms" /> </p> <button type="submit">Submit</button>
</EditForm> @functions { Person person = new Person(); void HandleValidSubmit() { Console.WriteLine("OnValidSubmit"); }
}

If you add this form to your app and run it you will get a basic form that automatically validates the field inputs when they are changed and when the form is submitted.

Validating form

There are quite a few things going on here, so let’s break it down piece by piece:

  • The form is defined using the new EditForm component. The EditForm sets up an EditContext as a cascading value that tracks metadata about the edit process (e.g. what’s been modified, current validation messages, etc.). The EditForm also provides convenient events for valid and invalid submits (OnValidSubmit, OnInvalidSubmit). Or you can use OnSubmit directly if you want to trigger the validation yourself.
  • The DataAnnotationsValidator component attaches validation support using data annotations to the cascaded EditContext. Enabling support for validation using data annotations currently requires this explicit gesture, but we are considering making this the default behavior that you can then override.
  • Each of the form fields are defined using a set of built-in input components (InputText, InputNumber, InputCheckbox, InputSelect, etc.). These components provide default behavior for validating on edit and changing their CSS class to reflect the field state. Some of them have useful parsing logic (e.g., InputDate and InputNumber handle unparseable values gracefully by registering them as validation errors). The relevant ones also support nullability of the target field (e.g., int?).
  • The ValidationMessage component displays validation messages for a specific field.
  • The ValidationSummary component summarizes all validation messages (similar to the validation summary tag helper).

There are some limitations with the built-in input components that we expect to improve in future updates. For example, you can’t currently specify arbitrary attributes on the generate input tags. In the future, we plan to enable components that pass through all extra attributes. For now, you’ll need to build your own component subclasses to handle these cases.

Runtime compilation

Support for runtime compilation was removed from the ASP.NET Core shared framework in .NET Core 3.0, but you can now enable it by adding a package to your app.

To enable runtime compilation:

  1. Add a package reference to Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation

    <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.0.0-preview3-19153-02" />
    
  2. In Startup.ConfigureServices add a call to AddRazorRuntimeCompilation

    services.AddMvc().AddRazorRuntimeCompilation();
    

Worker Service Template

In 3.0.0-preview3 we are introducing a new template called ‘Worker Service’. This template is designed as a starting point for running long-running background processes like you might run as a Windows Service or Linux Daemon. Examples of this would be producing/consuming messages from a message queue or monitoring a file to process when it appears. It’s intended to provide the productivity features of ASP.NET Core such as Logging, DI, Configuration, etc without carrying any web dependencies.

Worker Service

In the coming days we will publish a few blog posts giving more walkthroughs on using the Worker template to get started. We will have dedicated posts about publishing as a Windows/Systemd service, running on ACI/AKS, as well as running as a WebJob.

Caveats

Whilst the intent is for the worker template to not have any dependencies on web technologies by default, in preview3 it still uses the Web SDK and is shown after you select ‘ASP.NET Core WebApplication’ in Visual Studio. This is temporary and will be changed in a future preview. This means that for preview3 you will see many options in VS that may not make sense, such as publishing your worker as a web app to IIS.

Angular template updated to Angular 7

The Angular template is now updated to Angular 7. We anticipate updating again to Angular 8 before .NET Core 3.0 ships a stable release.

Authentication for the Single Page Application templates

This release introduces support for authentication in our Angular and React templates. In this section we show how to create a new Angular or React template that allows us to authenticate users and access a protected API resource.

Our support for authenticating and authorizing users is powered behind the scenes by IdentityServer, with some extensions we built to simplify the configuration experience for the scenarios we are targeting.

Note: In this post we showcase authentication support for Angular but the React template offers equivalent functionality.

Create a new Angular application

To create a new Angular application with authentication support we invoke the following command:

dotnet new angular -au Individual

This command creates a new ASP.NET Core application with a hosted client Angular application. The ASP.NET Core application includes an Identity Server instance already configured so that your Angular application can authenticate users and send HTTP requests against the protected resources in the ASP.NET Core application.

The authentication and authorization support is built as an Angular module that gets imported into your application and offers a suite of components and services to enhance the functionality of the main applicaiton module.

Run the application

To run the application simply execute the command below and open the browser in the url displayed on the console:

dotnet run
Hosting environment: Development
Content root path: C:\angularapp
Now listening on: https://localhost:5001
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

SPA index

When we open the application we see the usual Home, Counter and Fetch data menu options and two new options: Register and Login. If we click on Register we get sent to the default Identity UI where (after running migrations and updating the database) we can register as a new user.

Register a new user

SPA register

After registering as a new user we get redirected back to the application where we can see that we are successfully authenticated

SPA logged in

Call an authenticated API

If we click on the Fetch data we can see the weather forecast data table

SPA fetch data

Protect an existing API

To protect an API on the server we simply need to use the [Authorize] attribute on the controller or action that we want to protect.

[Authorize]
[Route("api/[controller]")]
public class SampleDataController : Controller
{
...
}

Require authentication for a client route.

To require the user be authenticated when visiting a page in the Angular application we apply the [AuthorizeGuard] to the route we are configuring.

import { ApiAuthorizationModule } from 'src/api-authorization/api-authorization.module';
import { AuthorizeGuard } from 'src/api-authorization/authorize.guard';
import { AuthorizeInterceptor } from 'src/api-authorization/authorize.interceptor'; @NgModule({ declarations: [ AppComponent, NavMenuComponent, HomeComponent, CounterComponent, FetchDataComponent ], imports: [ BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }), HttpClientModule, FormsModule, ApiAuthorizationModule, RouterModule.forRoot([ { path: '', component: HomeComponent, pathMatch: 'full' }, { path: 'counter', component: CounterComponent }, { path: 'fetch-data', component: FetchDataComponent, canActivate: [AuthorizeGuard] }, ]) ], providers: [ { provide: HTTP_INTERCEPTORS, useClass: AuthorizeInterceptor, multi: true } ], bootstrap: [AppComponent]
})
export class AppModule { }

Get more details by visiting the docs page

This is a quick introduction to what our new authentication support for Single Page Applications has to offer. For more details check out the docs.

Endpoint Routing with SignalR Hubs

In 3.0.0-preview3 we are hooking SignalR hubs into the new Endpoint Routing feature recently released. SignalR hub wire-up was previously done explicitly:

app.UseSignalR(routes =>
{ routes.MapHub<ChatHub>("hubs/chat");
});

This meant developers would need to wire up controllers, Razor pages, and hubs in a variety of different places during startup, leading to a series of nearly-identical routing segments:

app.UseSignalR(routes =>
{ routes.MapHub<ChatHub>("hubs/chat");
}); app.UseRouting(routes =>
{ routes.MapRazorPages();
});

Now, SignalR hubs can also be routed via endpoint routing, so you’ve got a one-stop place to route nearly everything in ASP.NET Core.

app.UseRouting(routes =>
{ routes.MapRazorPages(); routes.MapHub<ChatHub>("hubs/chat");
});

Long Polling for Java SignalR Client

We added long polling support to the Java client which enables it to establish connections even in environments that do not support WebSockets. This also gives you the ability to specifically select the long polling transport in your client apps.

gRPC Template

This preview release introduces a new template for building gRPC services with ASP.NET Core using a new gRPC framework we are building in collaboration with Google.

gRPC is a popular RPC (remote procedure call) framework that offers an opinionated contract-first approach to API development. It uses HTTP/2 for transport, Protocol Buffers as the interface description language, and provides features such as authentication, bidirectional streaming and flow control, and cancellation and timeouts.

gRPC template

The templates create two projects: a gRPC service hosted inside ASP.NET Core, and a console application to test it with.

gRPC solution

This is the first public preview of gRPC for ASP.NET Core and it doesn’t implement all of gRPC’s features, but we’re working hard to make the best gRPC experience for ASP.NET possible. Please try it out and give us feedback at grpc/grpc-dotnet on GitHub.

Stay tuned for future blog posts discussing gRPC for ASP.NET Core in more detail.

Give feedback

We hope you enjoy the new features in this preview release of ASP.NET Core! Please let us know what you think by filing issues on Github.

Daniel Roth
Daniel Roth

Principal Program Manager, ASP.NET

Follow Daniel   

<!–


–>

post

Blazor 0.8.0 experimental release now available

Blazor 0.8.0 is now available! This release updates Blazor to use Razor Components in .NET Core 3.0 and adds some critical bug fixes.

Get Blazor 0.8.0

To get started with Blazor 0.8.0 install the following:

  1. .NET Core 3.0 Preview 2 SDK (3.0.100-preview-010184)
  2. Visual Studio 2019 (Preview 2 or later) with the ASP.NET and web development workload selected.
  3. The latest Blazor extension from the Visual Studio Marketplace.
  4. The Blazor templates on the command-line:

    dotnet new -i Microsoft.AspNetCore.Blazor.Templates::0.8.0-preview-19104-04
    

You can find getting started instructions, docs, and tutorials for Blazor at https://blazor.net.

Upgrade to Blazor 0.8.0

To upgrade your existing Blazor apps to Blazor 0.8.0 first make sure you’ve installed the prerequisites listed above.

To upgrade a standalone Blazor 0.7.0 project to 0.8.0:

  • Update the Blazor packages and .NET CLI tool references to 0.8.0-preview-19104-04.
  • Replace any package reference to Microsoft.AspNetCore.Blazor.Browser with a reference to Microsoft.AspNetCore.Blazor.
  • Replace BlazorComponent with ComponentBase.
  • Update overrides of SetParameters on components to override SetParametersAsync instead.
  • Replace BlazorLayoutComponent with LayoutComponentBase
  • Replace IBlazorApplicationBuilder with IComponentsApplicationBuilder.
  • Replace any using statements for Microsoft.AspNetCore.Blazor.* with Microsoft.AspNetCore.Components.*, except leave Microsoft.AspNetCore.Blazor.Hosting in Program.cs
  • In index.html update the script reference to reference components.webassembly.js instead of blazor.webassembly.js

To upgrade an ASP.NET Core hosted Blazor app to 0.8.0:

  • Update the client-side Blazor project as described previously.
  • Update the ASP.NET Core app hosting the Blazor app to .NET Core 3.0 by following the migrations steps in the ASP.NET Core docs.
    • Update the target framework to be netcoreapp3.0
    • Remove any package reference to Microsoft.AspNetCore.App or Microsoft.AspNetCore.All
    • Upgrade any non-Blazor Microsoft.AspNetCore.* package references to version 3.0.0-preview-19075-0444
    • Remove any package reference to Microsoft.AspNetCore.Razor.Design
    • To enable JSON support, add a package reference to Microsoft.AspNetCore.Mvc.NewtonsoftJson and updateStartup.ConfigureServices to call services.AddMvc().AddNewtonsoftJson()
  • Upgrade the Microsoft.AspNetCore.Blazor.Server package reference to 0.8.0-preview-19104-04
  • Add a package reference to Microsoft.AspNetCore.Components.Server
  • In Startup.ConfigureServices simplify any call to app.AddResponseCompression to call the default overload without specifying WebAssembly or binary data as additional MIME types to compress.
  • In Startup.Configure add a call to app.UseBlazorDebugging() after the existing call to app.UseBlazor<App.Startup>()
  • Remove any unnecessary use of the Microsoft.AspNetCore.Blazor.Server namespace.

To upgrade a Blazor class library to 0.8.0:

  • Replace the package references to Microsoft.AspNetCore.Blazor.Browser and Microsoft.AspNetCore.Blazor.Build with references to Microsoft.AspNetCore.Components.Browser and Microsoft.AspNetCore.Components.Build and update the versions to 3.0.0-preview-19075-0444.
  • In the project file for the library change the project SDK from “Microsoft.NET.Sdk.Web” to “Microsoft.NET.Sdk.Razor”.

Server-side Blazor is now ASP.NET Core Razor Components in .NET Core 3.0

As was recently announced, server-side Blazor is now shipping as ASP.NET Core Razor Components in .NET Core 3.0. We’ve integrated the Blazor component model into ASP.NET Core 3.0 and renamed it to Razor Components. Blazor 0.8.0 is now built on Razor Components and enables you to host Razor Components in the browser on WebAssembly.

Upgrade a server-side Blazor project to ASP.NET Core Razor Components in .NET Core 3.0

If you’ve been working with server-side Blazor, we recommend upgrading to use ASP.NET Core Razor Components in .NET Core 3.0.

To upgrade a server-side Blazor app to ASP.NET Core Razor Components:

  • Update the client-side Blazor project as described previously, except replace the script reference to blazor.server.js with components.server.js
  • Update the ASP.NET Core app hosting the Razor Components to .NET Core 3.0 as described previously.
  • In the server project:
    • Upgrade the Microsoft.AspNetCore.Blazor.Server package reference to 0.8.0-preview-19104-04
    • Add a package reference to Microsoft.AspNetCore.Components.Server version 3.0.0-preview-19075-0444
    • Replace the using statement for Microsoft.AspNetCore.Blazor.Server with Microsoft.AspNetCore.Components.Server
    • Replace services.AddServerSideBlazor with services.AddRazorComponents and app.UseServerSideBlazor with app.UseRazorComponents.
    • In the Startup.Configure method add app.UseStaticFiles() just prior to calling app.UseRazorComponents.
    • Move the wwwroot folder from the Blazor app project to the ASP.NET Core server project

Switching between ASP.NET Core Razor Components and client-side Blazor

Sometimes it’s convenient to be able to switch between running your Razor Components on the server (ASP.NET Core Razor Components) and on the client (Blazor). For example, you might run on the server during development so that you can easily debug, but then publish your app to run on the client.

To update an ASP.NET Core hosted Blazor app so that it can be run as an ASP.NET Core Razor Components app:

  • Move the wwwroot folder from the client-side Blazor project to the ASP.NET Core server project.
  • In the server project:
    • Update the script tag in index.html to point to components.server.js instead of components.webassembly.js.
    • Add a call to services.AddRazorComponents<Client.Startup>() in the Startup.ConfigureServices method.
    • Add a call to app.UseStaticFiles() in the Startup.Configure method prior to the call to UseMvc.
    • Replace the call to UseBlazor with app.UseRazorComponents<Client.Startup>()
  • If you’re using dependency injection to inject an HttpClient into your components, then you’ll need to add an HttpClient as a service in your server’s Startup.ConfigureServices method.

Previously to get tooling support for Blazor projects you needed to install the Blazor extension for Visual Studio. Starting with Visual Studio 2019 Preview 2, tooling support for Razor Components (and hence Blazor apps) is already included without having to install anything else. The Blazor extension is now only needed to install the Blazor project templates in Visual Studio.

Runtime improvements

Blazor 0.8.0 includes some .NET runtime improvements like improved runtime performance on Chrome and an improved IL linker. In our performance benchmarks, Blazor 0.8.0 performance on Chrome is now about 25% faster. You can now also reference existing libraries like Json.NET from a Blazor app without any additional linker configuration:

@functions {
 WeatherForecast[] forecasts;

 protected override async Task OnInitAsync()
 {
 var json = await Http.GetStringAsync("api/SampleData/WeatherForecasts");
 forecasts = Newtonsoft.Json.JsonConvert.DeserializeObject<WeatherForecast[]>(json);
 }
}

Known issues

There are a couple of known issues with this release that you may run into:

  • “It was not possible to find any compatible framework version. The specified framework ‘Microsoft.NETCore.App’, version ‘2.0.0’ was not found.”: You may see this error when building a Blazor app because the IL linker currently requires .NET Core 2.x to run. To work around this issue, either install .NET Core 2.2 or disable IL linking by setting the <BlazorLinkOnBuild>false</BlazorLinkOnBuild> property in your project file.
  • “Unable to generate deps.json, it may have been already generated.”: You may see this error when running a standalone Blazor app and you haven’t yet restored packages for any .NET Core apps. To workaround this issue create any .NET Core app (ex dotnet new console) and then rerun the Blazor app.

These issues will be addressed in a future Blazor update.

Future updates

This release of Blazor was primarily focused on first integrating Razor Components into ASP.NET Core 3.0 and then rebuilding Blazor on top of that. Going forward, we plan to ship Blazor updates with each .NET Core 3.0 update.

Blazor, and support for running Razor Components on WebAssembly in the browser, won’t ship with .NET Core 3.0, but we continue to work towards shipping Blazor some later date.

Give feedback

We hope you enjoy this latest preview release of Blazor. As with previous releases, your feedback is important to us. If you run into issues or have questions while trying out Blazor, file issues on GitHub. You can also chat with us and the Blazor community on Gitter if you get stuck or to share how Blazor is working for you. After you’ve tried out Blazor for a while please let us know what you think by taking our in-product survey. Click the survey link shown on the app home page when running one of the Blazor project templates:

Blazor survey

Thanks for trying out Blazor!