October 17th, 2018

ASP.NET Core 2.2.0-preview3 now available

Glenn Condron [MSFT]
Principal Program Manager

Today we’re very happy to announce that the third preview of the next minor release of ASP.NET Core and .NET Core is now available for you to try out. We’ve been working hard on this release, along with many folks from the community, and it’s now ready for a wider audience to try it out and provide the feedback that will continue to shape the release.

How do I get it?

You can download the new .NET Core SDK for 2.2.0-preview3 (which includes ASP.NET 2.2.0-preview3) from

https://www.microsoft.com/net/download/dotnet-core/2.2

Visual Studio requirements

Customers using Visual Studio should also install and use the Preview channel of Visual Studio 2017 (15.9 Preview 3 or later) in addition to the SDK when working with .NET Core 2.2 and ASP.NET Core 2.2 projects. Please note that the Visual Studio preview channel can be installed side-by-side with existing an Visual Studio installation without disrupting your current development environment.

Azure App Service Requirements

If you are hosting your application on Azure App Service, you can follow these instructions to install the required site extension for hosting your 2.2.0-preview3 applications.

Impact to machines

Please note that is a preview release and there are likely to be known issues and as-yet-to-be discovered bugs. While the .NET Core SDK and runtime installs are side-by-side, your default SDK will become the latest one. If you run into issues working on existing projects using earlier versions of .NET Core after installing the preview SDK, you can force specific projects to use an earlier installed version of the SDK using a

global.json file as documented here. Please log an issue if you run into such cases as SDK releases are intended to be backwards compatible.

What’s new in Preview 3

For a full list of changes, bug fixes, and known issues you can read the release announcement.

Routing

We’ve introduced the concept of Parameter Transformers to routing in ASP.NET Core 2.2. A parameter transformer customizes the route generated by transforming parameter’s route values, and gives developers new options when generating routes. For example, a custom slugify parameter transformer in route pattern blog\{article:slugify} with Url.Action(new { article = "MyTestArticle" }) generates blog\my-test-article. Parameter transformers implement Microsoft.AspNetCore.Routing.IOutboundParameterTransformer and are configured using ConstraintMap. These features are specific to the new endpoint routing system used in MVC by default in 2.2. Parameter transformers are also used by frameworks to transform the URI to which an endpoint resolves. For example, ASP.NET Core MVC uses parameter transformers to transform the route value used to match an area, controller, action, and page.

routes.MapRoute(
    name: "default",
    template: "{controller=Home:slugify}/{action=Index:slugify}/{id?}");

With the preceding route, the action SubscriptionManagementController.GetAll() is matched with the URI /subscription-management/get-all. A parameter transformer doesn’t change the route values used to generate a link. Url.Action("GetAll", "SubscriptionManagement") outputs /subscription-management/get-all. ASP.NET Core provides API conventions for using a parameter transformers with generated routes: * MVC has the Microsoft.AspNetCore.Mvc.ApplicationModels.RouteTokenTransformerConvention API convention. This convention applies a specified parameter transformer to all attribute routes in the app. The parameter transformer will transform attribute route tokens as they are replaced. For more information, see Use a parameter transformer to customize token replacement. * Razor pages has the Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteTransformerConvention API convention. This convention applies a specified parameter transformer to all automatically discovered Razor pages. The parameter transformer will transform the folder and file name segments of Razor page routes. For more information, see Use a parameter transformer to customize page routes.

Link Generation

Added a new service called LinkGenerator, it is a singleton service that supports generating paths and absolute URIs both with and without an HttpContext. If you need to generate links in Middleware or somewhere outside of Razor then this new service will be useful to you. You can use it in Razor, but the existing APIs like Url.Action are already backed by the new service so you can continue to use those.

return _linkGenerator.GetPathByAction(
     httpContext,
     controller: "Home",
     action: "Index",
     values: new { id=42 });

For now this is useful to link to MVC actions and pages from outside of MVC. We will add additional features in the next release targeting non-MVC scenarios.

Health Checks

DbContextHealthCheck

We added a new DbContext based check for when you are using Entity Framework Core:

// Registers required services for health checks
services.AddHealthChecks()
        // Registers a health check for the MyContext type. By default the name of the health check will be the
        // name of the DbContext type. There are other options available through AddDbContextCheck to configure
        // failure status, tags, and custom test query.
        .AddDbContextCheck<MyContext>();

This check will make sure that the application can communicate with the database you configured for

MyContext. By default the DbContextHealthCheck will call the CanConnectAsync method that is being added to Entity Framework Core 2.2. You can customize what operation is run when checking health using overloads of the AddDbContextCheck method.

Health Check Publisher

We added the IHealthCheckPublisher interface that has a single method you can implement:

Task PublishAsync(HealthReport report, CancellationToken cancellationToken);

If you add an IHealthCheckPublisher to DI then the health checks system will periodically execute your health checks and call PublishAsync with the result. We expect this to be useful when you are interacting with a push based health system that expects each process to call it periodically in order to determine health.

Tags

In preview3 we added the ability to tag health checks with a list of strings when you register them:

services.AddHealthChecks()
        .AddDbContextCheck<MyContext>(tags: new[] { "db" });

Once you’ve done this then you can filter execution of your checks via tag:

app.UseHealthChecks("/liveness", new HealthCheckOptions
{
    Predicate = (_) => false
});

app.UseHealthChecks("/readiness", new HealthCheckOptions
{
    Predicate = (check) => check.Tags.Contains("db")
});

We see tags as a way for consumers of health checks, application authors, to use as a convenient grouping and filtering mechanism for their health checks. Not something that health check authors will pre-populate. You can also customize what status a failure of this check means for your application, for example if your application is written such that it can handle the database not being available then a database being down might mean Degraded rather than UnHealthy.

Validation Performance Improvements

MVC’s validation system is designed to be extensible and flexible allowing developer to determine on a per request basis what validators apply to a given model. This is great for authoring complex validation providers. However, in the most common case your application only uses the built-in validation pieces such as DataAnnotations ([Required], [StringLength] etc, or IValidatableObject) and don’t require this extra flexability. In 2.2.0-preview3, we’re adding a feature that allows MVC to short-circuit validation if it can determine that a given model graph would not require any validation. This results in significant improvements when validating models that cannot or do not have any associated validators. This includes objects such as collections of primitives (byte[], string[], Dictionary<string, string> etc), or complex object graphs without many validators. For this model – https://github.com/aspnet/Mvc/blob/release/2.2/benchmarkapps/BasicApi/Models/Pet.cs – the table below compares the difference in Requests Per Second (RPS) with and without the enhancement:

Description RPS Memory (MB) Avg. Latency (ms) Startup (ms) First Request (ms) Ratio
Baseline 78,738 398 3.5 547 111.3 1.00
Validation changes 90,167 401 2.9 541 115.9 1.15

HTTP Client Performance Improvements

Some significant performance improvements have been made to SocketsHttpHandler by improving the connection pool locking contention. For applications making many outgoing HTTP requests, such as some Microservices architectures, throughput should be significantly improved. Our internal benchmarks show that under load HttpClient throughput has improved by 60% on Linux and 20% on Windows. At the same time the 90th percentile latency was cut down by two on Linux. See Github #32568 for the actual code change that made this improvement. Requests Per Second Linux (higher is better) image Requests Per Second Windows (higher is better) image Request Latency Linux (lower is better) image Request Latency Windows (lower is better) image

ASP.NET Core Module

We added support for the ability to detect client disconnects when you’re using the new IIS in-process hosting model. The HttpContext.RequestAborted cancellation token now gets tripped when your client disconnnects. The ASP.NET Core Module also features enhanced diagnostics logs that configurable via the new handler settings or environment variables that expose a higher fidelity of diagnostic information.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath="dotnet" arguments=".\clientdisconnect.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess">
        <handlerSettings>
          <handlerSetting name="debugFile" value="debug.txt" />
          <handlerSetting name="debugLevel" value="TRACE" />
        </handlerSettings> 
      </aspNetCore>
    </system.webServer>
  </location>
</configuration>

SignalR Java Client

Preview 3 includes a few notable changes to the SignalR Java Client as we progress towards a 1.0 release: The “groupId” for the Maven package has changed to com.microsoft.signalr. To reference the new package from a Maven POM file, add the following dependency:

<dependency>
    <groupId>com.microsoft.signalr</groupId>
    <artifactId>signalr</artifactId>
    <version>1.0.0-preview3-35501</version>
</dependency>

Or in Gradle:

implementation 'com.microsoft.signalr:signalr:1.0.0-preview3-35501'

In Preview 3 we’ve changed all the APIs to be asynchronous, using

RxJava. Our Java Client documentation will be updated to show the new usage patterns. We also have support for the invoke method, allowing the client code to wait for the server method to complete. This version also includes support for serializing custom types in method arguments and return values. The Java Client currently requires Android API Level 26 (or higher). We are investigating moving down to a lower API level before RTM. If you are planning to use SignalR in an Java-based Android application, please comment on the GitHub issue tracking our Android API level support so we know what API level would work well for our users.

Migrating an ASP.NET Core 2.1 project to 2.2

To migrate an ASP.NET Core project from 2.1.x to 2.2.0-preview3, open the project’s .csproj file and change the value of the the element to netcoreapp2.2. You do not need to do this if you’re targeting .NET Framework 4.x.

Giving Feedback

The main purpose of providing previews is to solicit feedback so we can refine and improve the product in time for the final release. Please help provide us feedback by logging issues in the appropriate repository at https://github.com/aspnet or https://github.com/dotnet. We look forward to receiving your feedback!

Author

Glenn Condron [MSFT]
Principal Program Manager

0 comments

Discussion are closed.