ASP.NET Core updates in .NET Core 3.1 Preview 2

Daniel Roth

.NET Core 3.1 Preview 2 is now available. This release is primarily focused on bug fixes, but it contains a few new features as well.

Here’s what’s new in this release for ASP.NET Core:

  • New component tag helper
  • Prevent default actions for events in Blazor apps
  • Stop event propagation in Blazor apps
  • Validation of nested models in Blazor forms
  • Detailed errors during Blazor app development

See the release notes for additional details and known issues.

Get started

To get started with ASP.NET Core in .NET Core 3.1 Preview 2 install the .NET Core 3.1 Preview 2 SDK.

If you’re on Windows using Visual Studio, for the best experience we recommend installing the latest preview of Visual Studio 2019 16.4. Installing Visual Studio 2019 16.4 will also install .NET Core 3.1 Preview 2, so you don’t need to separately install it. For Blazor development with .NET Core 3.1, Visual Studio 2019 16.4 is required.

Alongside this .NET Core 3.1 Preview 2 release, we’ve also released a Blazor WebAssembly update. To install the latest Blazor WebAssembly template also run the following command:

dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.1.0-preview2.19528.8

Upgrade an existing project

To upgrade an existing ASP.NET Core 3.1 Preview 1 project to 3.1 Preview 2:

  • Update all Microsoft.AspNetCore.* package references to 3.1.0-preview2.19528.8

See also the full list of breaking changes in ASP.NET Core 3.1.

That’s it! You should now be all set to use .NET Core 3.1 Preview 2!

New component tag helper

Using Razor components from views and pages is now more convenient with the new component tag helper.

Previously, rendering a component from a view or page involved using the RenderComponentAsync HTML helper.

@(await Html.RenderComponentAsync<Counter>(RenderMode.ServerPrerendered, new { IncrementAmount = 10 }))

The new component tag helper simplifies the syntax for rendering components from pages and views. Simply specify the type of the component you wish to render as well as the desired render mode. You can also specify component parameters using attributes prefixed with param-.

<component type="typeof(Counter)" render-mode="ServerPrerendered" param-IncrementAmount="10" />

The different render modes allow you to control how the component is rendered:

RenderMode Description
Static Renders the component into static HTML.
Server Renders a marker for a Blazor Server application. This doesn’t include any output from the component. When the user-agent starts, it uses this marker to bootstrap the Blazor app.
ServerPrerendered Renders the component into static HTML and includes a marker for a Blazor Server app. When the user-agent starts, it uses this marker to bootstrap the Blazor app.

Prevent default actions for events in Blazor apps

You can now prevent the default action for events in Blazor apps using the new @oneventname:preventDefault directive attribute. For example, the following component displays a count in a text box that can be changed by pressing the “+” or “-” keys:

<p>Press "+" or "-" in change the count.</p>
<input value="@count" @onkeypress="@KeyHandler" @onkeypress:preventDefault />

@code {
    int count = 0;

    void KeyHandler(KeyboardEventArgs ev)
        if (ev.Key == "+")
        else if (ev.Key == "-")

The @onkeypress:preventDefault directive attribute prevents the default action of showing the text typed by the user in the text box. Specifying this attribute without a value is equivalent to @onkeypress:preventDefault="true". The value of the attribute can also be an expression: @onkeypress:preventDefault="shouldPreventDefault". You don’t have to define an event handler to prevent the default action; both features can be used independently.

Stop event propagation in Blazor apps

Use the new @oneventname:stopPropagation directive attribute to stop event propagation in Blazor apps.

In the following example, checking the checkbox prevents click events from the child div from propagating to the parent div:

<input @bind="stopPropagation" type="checkbox" />
<div @onclick="OnClickParentDiv">
    Parent div
    <div @onclick="OnClickChildDiv" @onclick:stopPropagation="stopPropagation">
        Child div

<button @onclick="OnClick">Click me!</button>

@code {
    bool stopPropagation;

    void OnClickParentDiv() => Console.WriteLine("Parent div clicked.");
    void OnClickChildDiv() => Console.WriteLine("Child div clicked.");

Detailed errors during Blazor app development

When your Blazor app isn’t functioning properly during development, it’s important to get detailed error information so that you can troubleshoot and fix the issues. Blazor apps now display a gold bar at the bottom of the screen when an error occurs.

During development, in Blazor Server apps, the gold bar will direct you to the browser console where you can see the exception that has occurred.

Blazor detailed errors in development

In production, the gold bar notifies the user that something has gone wrong, and recommends the user to refresh the browser.

Blazor detailed errors in production

The UI for this error handling experience is part of the updated Blazor project templates so that it can be easily customized:


<div id="blazor-error-ui">
    <environment include="Staging,Production">
        An error has occurred. This application may no longer respond until reloaded.
    <environment include="Development">
        An unhandled exception has occurred. See browser dev tools for details.
    <a href="" class="reload">Reload</a>
    <a class="dismiss">🗙</a>

Validation of nested models in Blazor forms

Blazor provides support for validating form input using data annotations with the built-in DataAnnotationsValidator. However, the DataAnnotationsValidator only validates top-level properties of the model bound to the form.

To validate the entire object graph of the bound model, try out the new ObjectGraphDataAnnotationsValidator available in the experimental Microsoft.AspNetCore.Blazor.DataAnnotations.Validation package:

<EditForm Model="@model" OnValidSubmit="@HandleValidSubmit">
    <ObjectGraphDataAnnotationsValidator />

The Microsoft.AspNetCore.Blazor.DataAnnotations.Validation is not slated to ship with .NET Core 3.1, but is provided as an experimental package to get early feedback.

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.

Thanks for trying out ASP.NET Core!


Discussion is closed. Login to edit/delete existing comments.

  • Claas Möhlmann 0

    Really love these changes and seeing Blazor growing

  • Kevin Gates 0

    This is great! Will prevent default work like JavaScript’s prevent default?

    For instance if we use NavLink component, but we occasionally want to have a “confirmation box” before one navigates away, will this now be possible?

    So someone is creating an order, they go to click away. If they click away, we will lose the state. Therefore having a preventDefault action on the link will allow us to show a confirmation model. And if “yes”, then continue with the normal behavior of the link.

    • Daniel RothMicrosoft employee 0

      Yes, that should now be possible. If you find otherwise, let us know!

  • Ricardo Soares 0

    I created a simple RCL and added an new component called Label with the default template content
    and add OnAfterRenderAsync on that component:

    @inject  IJSRuntime  JSRuntime
    @code {
        protected override async Task OnAfterRenderAsync(bool firstRender)
            if (firstRender)
               await JSRuntime.InvokeVoidAsync("exampleJsFunctions.writeToConsole", "Teste afterRender");

    And in soluction I add two new project one for Blazor and another for Razor Page application.

    So I place the component in Index.razor on Blazor and in Index.cshtml on Razor Page

    When I run the blazor project the OnAfterRenderAsync is called
    but, when I run Razor Page application the method is not called.

    Another thing I’m think is how to use a Template Component on MVC and Razor Page using TagHelp or HTML helper?

    • Daniel RothMicrosoft employee 0

      The OnAfterRender lifecycle event isn’t called when prerendering from a .cshtml file. See

      The parameters you pass to a top-level component need to be serializable, so there isn’t a good way to use a templated component as a top-level component. But you can wrap the templated component in a new component and pass data through.

  • Ahmed Abu El-Noor 0

    I really love Blazor but it really miss an important feature, how for up till now, there is no built-in support for file(s)?

    I can’t upload a file or set of files? I have to deal with such of libraries and bunch of other codes to just upload a file

    Please we hope to see it in the next preview

  • Markus Rodler 0

    I have a question about preventDefault. Is it now possible to preventDefault only for some keys? For example i want to preventDefault on a textfield if the enter key is pressed. In JavaScript I would write it like this:

    document.getElementById('div').keypress(function (event) {
        if (event.which === 13) {
  • R BROWN 0

    Blazor is great! I thought I’d just get that off my chest 🙂

    The “ObjectGraphDataAnnotationsValidator” works on the client-side but not on the server(api) side. It crashs with the error:

    System.InvalidOperationException: ValidateComplexTypeAttribute can only used with ObjectGraphDataAnnotationsValidator.
    at System.ComponentModel.DataAnnotations.ValidateComplexTypeAttribute.IsValid(Object value, ValidationContext validationContext)
    at System.ComponentModel.DataAnnotations.ValidationAttribute.GetValidationResult(Object value, ValidationContext validationContext)
    at Microsoft.AspNetCore.Mvc.DataAnnotations.DataAnnotationsModelValidator.Validate(ModelValidationContext validationContext)
    at Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.ValidateNode()
    at Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitComplexType(IValidationStrategy defaultStrategy)
    at Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.Visit(ModelMetadata metadata, String key, Object model)
    at Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitChildren(IValidationStrategy strategy)
    at Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitComplexType(IValidationStrategy defaultStrategy)
    at Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.Visit(ModelMetadata metadata, String key, Object model)
    at Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.Validate(ModelMetadata metadata, String key, Object model, Boolean alwaysValidateAtTopLevel)
    at Microsoft.AspNetCore.Mvc.ModelBinding.ObjectModelValidator.Validate(ActionContext actionContext, ValidationStateDictionary validationState, String prefix, Object model, ModelMetadata metadata)

    • Daniel RothMicrosoft employee 0

      Thanks for trying out our preview features! The ObjectGraphDataAnnotationsValidator should work with Blazor Server. Could you please open a GitHub issue with detailed steps on how to reproduce the issue you are seeing?:

      • R BROWN 0

        I can now see my post was a bit misleading…..The blazor app I built was the WebAssembly version (ASP.NET Core hosted). I will open up a Github issue.

  • Mohamed Radwan 0

    This video will show step-by-step ASP.NET Core development with Deployment to Azure with animated workflow which help you clearly understand it.

  • Nemo 0

    Hi, it’s great to see all the improvements and updates going into Blazor! A general question, is it possible to mix React or Angular components with Blazor?

    • Daniel RothMicrosoft employee 0

      It’s possible as long as long as you don’t try to overlay the two component models. Both Blazor and Angular assume they control the DOM so that they can efficiently calculate what changes were rendered by their respective components. As long as you keep Blazor and Angular in their own separate islands in the DOM you should be fine.

      • Nemo 0

        Thanks Daniel! Another question, does the DOM diffing algorithm in StateHasChanged() take into account elements which are not visible and ignore them? E.g. if there is a table with 100 rows and columns, but if only the first 50 rows and 30 columns are visible, will DOM updates be pushed for the bottom 50 rows and 70 columns which are not visible? If the DOM diffing algorithm can track the visibility of elements and render accordingly, it would be really efficient and would let us build high frequency real-time user interfaces. Thank you.

  • Văn Lưu Thiện 0

    I don’t have blazorhosted:

    dotnet --info
    C:\Windows\system32>dotnet --info
    .NET Core SDK (reflecting any global.json):
     Version:   3.1.100
     Commit:    cd82f021f4
    Runtime Environment:
     OS Name:     Windows
     OS Version:  6.3.9600
     OS Platform: Windows
     RID:         win81-x64
     Base Path:   C:\Program Files\dotnet\sdk\3.1.100\
    Host (useful for support):
      Version: 3.1.0
      Commit:  65f04fb6db
    .NET Core SDKs installed:
      3.1.100-preview3-014645 [C:\Program Files\dotnet\sdk]
      3.1.100 [C:\Program Files\dotnet\sdk]
    .NET Core runtimes installed:
      Microsoft.AspNetCore.All 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.AspN
      Microsoft.AspNetCore.App 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.AspN
      Microsoft.AspNetCore.App 3.1.0-preview3.19555.2 [C:\Program Files\dotnet\share
      Microsoft.AspNetCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNe
      Microsoft.NETCore.App 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.NETCore
      Microsoft.NETCore.App 3.1.0-preview3.19553.2 [C:\Program Files\dotnet\shared\M
      Microsoft.NETCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.
      Microsoft.WindowsDesktop.App 3.1.0-preview3.19553.2 [C:\Program Files\dotnet\s
      Microsoft.WindowsDesktop.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.W
    To install additional .NET Core runtimes or SDKs:

    I was command, but blazorhosted not exist:

    dotnet new -i Microsoft.AspNetCore.Blazor.Templates::

    I install Visual Studio 2019 Preview with new version: SDKs is default

  • Dean Jackson 0

    I’m now using Core 3.1 after many years of making .Net Framework apps. It bugs me to see country folders (es, fr, etc.) in my bin output folder, and the “Runtimes” folder with Unix, etc. that I don’t need. I’m using Visual Studio 16.x to make ASP.Net Core apps.

    Can we prevent these folders from getting created? A post-build clean-up event would work, but I want to prevent it. Thanks.

Feedback usabilla icon