Introducing ASP.NET Core 2.0 Preview 2

At Build 2017, we released an initial preview version of ASP.NET Core 2.0.  Over the last two months we have incorporated your feedback and added a number of new features.  We now have a Preview 2 version of the ASP.NET Core 2.0 framework and Visual Studio tools for you to try.  In this post, we will review some of the new features in this preview release.

Update Visual Studio and install ASP.NET Core 2.0 Preview 2

If you don’t already have the latest Visual Studio 2017 Preview version installed on your Windows system, download the latest from

You can update an existing Visual Studio 2017 Preview installation using the Microsoft Visual Studio Installer application available on your start menu.  Choose to update Visual Studio 2017 Preview and the latest Visual Studio 2017 Preview 3 patch (15.3 Preview 3) will be downloaded and applied to your installation. For Mac users, you should install the Visual Studio for Mac and update to the latest preview from the Beta channel.

Next, download the latest .NET Core 2.0 SDK and install it.  This will give you an updated version of the .NET Core command-line tools and runtime.  You can verify that you have the correct version installed by executing the following at the command-line:

dotnet –-version

You should see the version “2.0.0-preview2-006497” reported, the current version of the 2.0 Preview 2 SDK.

SPA Templates for Everyone!

When you start the updated Visual Studio 2017 Preview and create a new ASP.NET Core website with .NET Core, you will notice that the ASP.NET template chooser for ASP.NET Core 2.0 shows some extra templates:

New ASP.NET Core Templates

The ASP.NET Core SPA templates for Angular and React are now available from Visual Studio.  They’re also available on the command-line as part of the standard installation of the .NET Core SDK.  Of particular note, the Angular template has been updated to Angular 4.  For more information about how to get started using the contents of the ASP.NET Core SPA templates, check the article from Steve Sanderson when the templates were initially made available.


ASP.NET Core 2 and .NET Framework

You can now choose to build your ASP.NET Core 2.0 applications with the .NET Framework by choosing the ASP.NET Core with .NET Framework template option in Visual Studio 2017.

Start a New ASP.NET Core Project with .NET Framework

Kestrel Improvements

We’ve added a number of server constraint configuration options to the Kestrel server through the KestrelServerOptions class’s new Limits property.  You can now add limits for the following:

  • Maximum Client Connections
  • Maximum Request Body Size
  • Maximum Request Body Data Rate

Maximum client connections

The maximum number of concurrent open HTTP/S connections can be set for the entire application with the following code:

.UseKestrel(options =>
    options.Limits.MaxConcurrentConnections = 100;
    options.Limits.MaxConcurrentUpgradedConnections = 100;

Note how there are two limits. Once a connection is upgraded from HTTP to another protocol (e.g. on a WebSockets request), it’s not counted against the limit anymore since upgraded connections have their own limit.

Maximum request body size

To configure the default constraint for the entire application:

.UseKestrel(options =>
    options.Limits.MaxRequestBodySize = 10 * 1024;

This will affect every request, unless it’s overridden on a specific request:

app.Run(async context =>
    context.Features.Get<IHttpMaxRequestBodySizeFeature>().MaxRequestBodySize = 10 * 1024;


You can only configure the limit on a request if the application hasn’t started reading yet, otherwise an exception is thrown. There’s an IsReadOnly property in the feature that tells you if the request body is in read-only state, meaning it’s too late to configure the limit.

Minimum request body data rate

To configure a default minimum request rate:

.UseKestrel(options =>
    options.Limits.RequestBodyMinimumDataRate = 
        new MinimumDataRate(rate: 100, gracePeriod: TimeSpan.FromSeconds(10));

To configure per-request:

app.Run(async context =>
    context.Features.Get<IHttpRequestBodyMinimumDataRateFeature>().MinimumDataRate = 
        new MinimumDataRate(rate: 100, gracePeriod: TimeSpan.FromSeconds(10));

The way the rate works is as follows: Kestrel will check every second if data is coming in at the specified rate in bytes/second. If the rate drops below the minimum, the connection is timed out. The grace period is the amount of time that Kestrel will give the client to get it’s send rate up to the minimum, so the rate is not checked during that time. This is to avoid dropping connections that are initially sending data at a slow rate due to TCP slow start.

Razor Support for C# 7.1

The Razor engine has been updated to work with the new Roslyn compiler and that includes support for C# 7.1 features like Default Expressions, Inferred Tuple Names, and Pattern-Matching with Generics.  To use C #7.1 features in your project add the following property in your project file and then reload the solution:


C# 7.1 is itself in a preview state, and you can review the language specification for these features on their GitHub repository.

Enhanced HTTP Header Support for Range, ETags, and LastUpdate

When using MVC to transmit a FileStreamResult or a FileContentResult, you now have the option to set an ETag or a LastModified date on the content you wish to transmit.  You can set these values on the returned content with code similar to the following:

var data = Encoding.UTF8.GetBytes("This is a sample text from a binary array");
var entityTag = new EntityTagHeaderValue("\"MyCalculatedEtagValue\"");
return File(data, "text/plain", "downloadName.txt", lastModified: DateTime.UtcNow.AddSeconds(-5), entityTag: entityTag);


The file returned to your visitors will be decorated with the appropriate HTTP headers for the ETag and Last Modified values.

If an application visitor requests content with a Range Request header, ASP.NET will recognize that and handle that header. If the requested content can be partially delivered, ASP.NET will appropriately skip and return just the requested set of bytes.  You do not need to write any special handlers into your methods to adapt or handle this feature, it is handled by the framework for you.

New Page Filters for Razor Pages

Page filters (IPageFilter, IAsyncPageFilter) allow you to run code before and after a page handler is executed, much in the same way that action filters let your run code before and after an action method is executed. Page filters can also influence which page handler gets executed or to run initialization code before model binding occurs. In Preview 2 you can add a page filter globally or using an app model convention. For preview 2 you can’t apply filters using attributes, but we expect this support to come later.

Azure App Service Support

The Preview 2 version of ASP.NET Core 2.0 can be deployed to Azure App Service with no changes needed.  Azure Data Centers are being rolled out today with completion scheduled for June 30th. You can track progress of the roll out on this Azure App Service Announcements issue.

Postponed features

Some features available in Preview 1 have been pulled out of the ASP.NET Core 2.0 release to give them more time to bake. We still plan to do these features, but for now they have been removed from Preview 2. These features are:

  • NET Core Identity as a Service, including the support for issue identity and access tokens using OpenID Connect and OAuth 2.0
  • Default configuration schema for configuring HTTPS, certificates and authentication (you can still configure logging by default).


This preview release delivers some of the promised features of the ASP.NET Core 2.0 framework, and we hope that you try them out.  You can find a complete set of release notes in the Home repository on GitHub with links to the feature issues and pull-requests that completed those features.  What do you think of the update to ASP.NET Core 2.0?  Let us know in the comments below.