Five months ago, we shipped ASP.NET Core 2.0 as a foundational release for our high performance, cross-platform web framework for .NET and .NET Core. Since then we have been hard at work to deliver the next wave of features in ASP.NET Core 2.1. Below is an outline of the features and improvements that are planned for this release, which is targeted for mid-year 2018.
Contents:
- MVC
- SignalR
- WebHooks
- GDPR
- Security
- Identity
- Options improvements
- HttpClientFactory
- Kestrel
- ASP.NET Core Module
- New Microsoft.AspNetCore.App package
MVC
Razor Pages improvements
In ASP.NET Core 2.0 we introduced Razor Pages as a new paged-based model for building Web UI. In 2.1 we are making a variety of improvements to Razor Pages to make it even more productive.
Razor Pages in an area
Areas provide a way to partition a large MVC app into smaller functional groupings each with their own controllers and views. In 2.1 we will add support for areas to Razor Pages so that areas can have their own pages directory.
Support for /Pages/Shared
In 2.1 Razor Pages will fall back to finding Razor assets such as layouts and partials in /[pages root]/Shared
before falling back to /Views/Shared
. In addition to this, pages themselves can now be in the /[pages root]/Shared
path and they will be routable as if they existed directly at /[pages root]/
, unless a page actually exists at that location, in which case it will be served instead.
Bind all properties on a page or controller
Starting in 2.0 you could use the BindPropertyAttribute
to specify that a property on a page model or controller should be bound to data from the request. If you have lots of properties that you want to bind, then this can get tedious and verbose. In 2.1 we will add support for specifying that all properties on a page or controller should be bound by putting the BindPropertyAttribute
on the class.
Implement IPageFilter on page models
We will implement IPageFilter
on page models, so that you can run logic before or after page handlers run for a given request, much the same way that you can implement IActionFilter
on a controller.
Functional testing infrastructure
Writing functional tests for an MVC app allows you to test handling of a request end-to-end including running routing, filters, controllers, actions, views and pages. While writing in-memory functional tests for MVC apps is possible with ASP.NET Core 2.0 it requires significant setup.
For 2.1 we will provide an test fixture implementation that handles the typical pitfalls when trying to test MVC applications using TestServer:
- Copy the .deps file from your project into the test assembly bin folder
- Specify the content root of the application’s project root so that static files and views can be found
- Streamline setting up your app on TestServer
A sample test that uses the new test fixture with xUnit looks like this:
See https://github.com/aspnet/announcements/issues/275 for additional details.
Web API improvements
ASP.NET Core gives you a single unified framework for building both Web UI and Web APIs. In 2.1 we are making various improvements to the
framework for building Web APIs.
Better Input Processing
We want the experience around invalid input to be more automatic and more consistent. More concretely we’re going to:
- Create a programming model where your action code isn’t called when a request has validation errors (see “Enhanced Web API controller conventions” below)
- Improve the fidelity of error responses when the request body fails to deserialize or the JSON is invalid
- Enable placing validation attributes directly on action parameters
Support for Problem Details
We are adding support for RFC 7808 – Problem Details for HTTP APIs as a standardized format for returning machine readable error responses from HTTP APIs. You can return a Problem Details response from your API action using the ValidationProblem()
helper method.
Improved OpenAPI specification support
We want to embrace the OpenAPI specification (previously called “Swagger”) and make Web APIs built with ASP.NET Core more descriptive. Today you need a lot of “attribute soup” to get a reasonable OpenAPI spec from ASP.NET Core. We plan to introduce an opinionated layer that infers the possible responses based on what you’re likely to have done with your actions (attributes still win when you want to be explicit).
For example, actions that return IActionResult
need to be attributed to indicate the return type so that the schema of the response body can be determined. Actions that return the response type directly don’t need to be attributed, but then you lose the flexibility to return any action result.
We will introduce a new ActionResult<T>
type that allows you to return either the response type or any action result, while still indicating the response type.
Enhanced Web API controller conventions and ActionResult<T>
We are adding the [ApiController]
attribute as the way to opt-in to Web API specific conventions and behaviors. These behaviors include:
- Automatically responding with a 400 when validation errors occur
- Infer smarter defaults for action parameters:
[FromBody]
for complex types,[FromRoute]
when possible, otherwise[FromQuery]
- Requires attribute routing – actions are not accessible by convention-based routes
Here’s an example Web API controller that uses these new enhancements:
Here’s what the Web API would look like if you were to implement it with 2.0:
JSON Patch improvements
For JSON Patch we will add support for the test operator and for patching dictionaries with non-string keys.
Partial Tag Helper
Razor partial views are a convenient way to include some Razor content into a view or page. Today there are four different methods for rendering a partial on a page that have different trade-offs and limitations (Html.Partial
vs Html.RenderPartial
, sync vs async). Rendering partials also suffers from a limitation where the generated prefix for rendered form elements based on the given model, must be handled manually for each partial rendering.
The new partial Tag Helper makes rendering a partial straightforward and elegant. You can specify the model using model expression syntax and the partial Tag Helper will handle setting up the correct HTML field prefix for you:
Razor UI in a class library
ASP.NET Core 2.1 will make it easier to build and include Razor based UI in a library and share it across multiple projects. A new Razor SDK will enable building Razor files into a class library project that can then be packaged into a NuGet package. Views and pages in libraries will automatically be discovered and can be overridden by the application. By integrating Razor compilation into the build, the app startup time is also significantly faster, while still allowing for fast updates to your Razor views and pages at runtime as part of an iterative development workflow.
SignalR
For ASP.NET Core 2.1 we are porting ASP.NET SignalR to ASP.NET Core to support real-time web scenarios. As previously announced, ASP.NET Core SignalR will also include a number of improvements, including a simplified scale-out model, a new JavaScript client with no jQuery dependency, a new compact binary protocol based on MessagePack, support for custom protocols, a new streaming response model, and support for clients based on bare WebSockets. You can start trying out ASP.NET Core SignalR today by checking out the samples.
WebHooks
WebHooks are a lightweight HTTP pattern for event notification across the web. WebHooks enable services to send event notifications over HTTP to registered subscribers. For 2.1 we are porting a subset of the ASP.NET WebHooks receivers to ASP.NET Core in a way that integrates with the ASP.NET Core idioms.
For 2.1 we plan to port the following receivers:
- Microsoft Azure alerts
- Microsoft Azure Kudu notifications
- Microsoft Dynamics CRM
- Bitbucket
- Dropbox
- GitHub
- MailChimp
- Pusher
- Salesforce
- Slack
- Stripe
- Trello
- WordPress
To use a WebHook receiver in ASP.NET Core WebHooks you attribute a controller action that you want to handle the notification. For example, here’s how you can handle an Azure alert:
Improvements for GDPR
The ASP.NET Core 2.1 project templates will include some extension points to help you meet some of your UE General Data Protection Regulation (GDPR) requirements.
A new cookie consent feature will allow you to ask for (and track) consent from your users for storing personal information. This can be combined with a new cookie feature where cookies can be marked as essential or non-essential. If a user has not consented to data collection, non-essential cookies will not be sent to the browser. You will still need to create the wording on the UI prompt and a suitable privacy policy which matches the GDPR analysis you or your company have performed, along with implementing the logic for determining under what conditions a given user should be asked for consent before writing non-essential cookies (the templates simply default to asking all users).
Additionally, the ASP.NET Core Identity templates for individual authentication now have a UI to allow users to download their personal data, along with the ability to delete their account entirely. By default, these UI areas only return personal information from ASP.NET Core identity, and perform a delete on the identity tables. As you add your own information into your database you should extend these features to also include that data according to your GDPR analysis.
Finally, we are considering extension points to allow you to apply your own encryption of ASP.NET Core identity data. We recommend that you examine the encryption features of your database to see if they match your GDPR requirements before attempting to layer on your own encryption mechanisms. Both Microsoft SQL and SQL Azure, as well as Azure table storage offer transparent encryption of data at rest, which does not require any changes to your application and is managed for you.
Security
HTTPS
With the increased focus on security and privacy, enabling HTTPS for web apps is more important than ever before. HTTPS enforcement is becoming increasingly strict on the web, and sites that don’t use it are considered, and increasingly labeled as, not secure. GDPR requires the use of HTTPS to protect user privacy. While using HTTPS in production is critical, using HTTPS during development can also help prevent related issues before deployment, like insecure links.
On by default
To facilitate secure website development, we are enabling HTTPS in ASP.NET Core 2.1 by default. Starting in 2.1, in addition to listing on http://localhost:5000, Kestrel will listen on https://localhost:5001 when a local development certificate is present. A suitable certificate will be created when the .NET Core SDK is installed or can be manually setup using the new ‘dev-certs’ tool. We will also update our project templates to run on HTTPS by default and include HTTPS redirection and HSTS support.
HTTPS redirection and enforcement
Web apps typically need to listen on both HTTP and HTTPS, but then redirect all HTTP traffic to HTTPS. ASP.NET Core 2.0 has URL rewrite middleware that can be used for this purpose, but it could be tricky to configure correctly. In 2.1 we are introducing specialized HTTPS redirection middleware that intelligently redirects based on the presence of configuration or bound server ports.
Use of HTTPS can be further enforced using HTTP Strict Transport Security Protocol (HSTS), which instructs browsers to always access the site via HTTPS. ASP.NET Core 2.1 adds HSTS middleware that supports options for max age, subdomains, and the HSTS preload list.
Configuration for production
In production, HTTPS must be explicitly configured. In 2.1 we are introducing default configuration schema for configuring HTTPS for Kestrel that is simple and straightforward. You can configure multiple endpoints including the URLs and the certificate to use for HTTPS either from a file on disk or from a certificate store:
Virtual authentication schemes
We’re adding something tentatively called “Virtual Schemes” to address two main scenarios:
- Making it easier to mix authentication schemes, like bearer tokens and cookie authentication in the same app (sample). Virtual schemes allow you to configure a dynamic authentication scheme that will use bearer authentication only for requests starting with /api, and cookie authentication otherwise
- Compose (mix/match) different authentication verbs (Challenge/SignIn/SignOut/Authenticate) across different handlers. For example, combining OAuth + Cookies, where you would have Challenge = OAuth, and everything else handled by cookies.
Identity
Identity as a library
ASP.NET Core Identity gives you a framework for setting up authentication and identity concerns for your site, including user registration, managing passwords, two-factor authentication, social logins and much more. However, setting up a site to use ASP.NET Core Identity requires quite a bit of code. While project templates help with generating this code, they don’t help with adding identity to an existing application and the code can’t easily be updated.
For 2.1 we will provide a default identity UI implementation as a library. You can add the default identity UI to your application by installing a NuGet package and then enable it in your Startup class:
Identity scaffolder
If you want all the identity code to be in your application so that you can change it however you want, you can use the new identity scaffolder to add the identity code to your application. All the scaffolded identity code is generated in an identity specific area folder so that it remains nicely separated from your application code.
Options improvements
To configure options with the help of configured services, you can today implement IConfigureOptions<T>
. In 2.1 we’re adding convenience overloads to the Configure
method that allow you to configure options using services without having to implement a separate class:
Also, the new ConfigureOptions<TSetup>
method lets you register a single class that configures multiple options (by implementing IConfigureOptions<T>
multiple times):
HttpClientFactory
The new HttpClientFactory
type can be registered and used to configure and consume instances of HttpClient
in your application. It provides several benefits:
- Provide a central location for naming and configuring logical instances of
HttpClient
. For example, you may configure a “github” client that is pre-configured to access GitHub and a default client for other purposes. - Codify the concept of outgoing middleware via delegating handlers in
HttpClient
and implementing Polly based middleware to take advantage of that. - Manage the lifetime of
HttpClientMessageHandlers
to avoid common problems that can be hit when managingHttpClient
lifetimes yourself.
HttpClient
already has the concept of delegating handlers that could be linked together for outgoing HTTP requests. The factory will make registering of these per named client more intuitive as well as implement a Polly handler that allows Polly policies to be used for Retry, CircuitBreakers, etc. Other “middleware” could also be implemented in the future but we don’t yet know when that will be.
In this first example we will configure two logical HttpClient
configurations, a default one with no name and a named “github” client.
Registration in Startup.cs:
Consumption in a controller:
In addition to using strings to differentiate configurations of HttpClient
, you can also leverage the DI system using what we are calling a typed client:
A class called GitHubService
:
This type can have behavior and completely encapsulate HttpClient
access if you wish, or just be used as a strongly typed way of naming an HttpClient
as shown here.
Registration in Startup.cs:
NOTE: The Polly section of this code sample should be considered pseudocode at best. We haven’t built this yet and as such are not sure of the final shape of the API.
Consumption in a Razor Page:
Kestrel
Transport Extensibility
The current implementation of the underlying libuv connection semantics has been decoupled from the rest of Kestrel and abstracted away into a new Transport abstraction. While we continue to ship with libuv as the default transport, we are also adding support for a new transport based on the socket types included in .NET.
Socket Transport
We are continuing to invest in a new socket transport for Kestrel as we believe it has the potential to be more performant than the existing libuv transport. While we aren’t quite there yet, you can still easily switch to the new socket transport and try it out today.
Default configuration
We are adding support to Kestrel for configuring endpoints and HTTPS settings (see HTTPS: Configuration for production)
ASP.NET Core Module
The ASP.NET Core Module (ANCM) is a global IIS module for IIS that acts as a reverse-proxy from IIS to your Kestrel backend.
Version agility
Since ANCM is a global singleton, it can’t version or ship with the same agility as the rest of the ASP.NET Core. In 2.1, we’ve refactored ANCM into two pieces: the shim and the request handler. The shim will continue to be installed as a global singleton, but the request handler will ship as part of the new Microsoft.AspNetCore.Server.IIS package which can be referenced directly by your application. This will allow you to use different versions of ANCM with different app deployments.
In-process hosting
In 2.1, we’re adding a new in-process mode to ANCM for .NET Core based apps where the runtime and your app are both loaded inside the IIS worker process (w3wp.exe). This removes the performance penalty of proxying requests over the loopback adapter. Our preliminary tests show performance improvements of around ~4.4x compared to running out-of-process. Configuring your app to use to use the in-process model can be done using `web.config`, and will be eventually be the default for new applications targeting 2.1:
Alternatively, you can set a project property in your project file:
New Microsoft.AspNetCore.App package
ASP.NET Core 2.1 will introduce a new meta-package for use by applications: Microsoft.AspNetCore.App. The new meta-package differs from the existing meta-package in that it reduces the number of dependencies of packages not owned or supported by the ASP.NET or .NET teams to just those deemed necessary to ensure the major framework features function. We will update project templates to use the new meta-package. The existing Microsoft.AspNetCore.All meta-package will continue to be made available throughout the 2.x lifecycle. For additional details see https://github.com/aspnet/Announcements/issues/287.
In conclusion
We hope you are as excited about these features and improvements as we are! Of course, it is still early in the release and these plans are subject to change, but you can follow along with the latest status of these features by tracking the action on GitHub. Major updates and changes will be posted on the Announcements repo. You can also get live updates and participate in the conversation by watching the weekly ASP.NET Community Standup at https://live.asp.net. You can also read about the roadmaps for .NET Core 2.1 and EF Core 2.0 on the .NET team blog. Your feedback is welcome and appreciated!