ASP.NET Core Architect David Fowler's hidden gems in 2.1
Open source ASP.NET Core 2.1 is out, and Architect David Fowler took to twitter to share some hidden gems that not everyone knows about. Sure, it's faster, builds faster, runs faster, but there's a number of details and fun advanced techniques that are worth a closer look at.
.NET Generic Host
ASP.NET Core introduced a new hosting model. .NET apps configure and launch a host.
The host is responsible for app startup and lifetime management. The goal of the Generic Host is to decouple the HTTP pipeline from the Web Host API to enable a wider array of host scenarios. Messaging, background tasks, and other non-HTTP workloads based on the Generic Host benefit from cross-cutting capabilities, such as configuration, dependency injection (DI), and logging.
This means that there's not just a WebHost anymore, there's a Generic Host for non-web-hosting scenarios. You get the same feeling as with ASP.NET Core and all the cool features like DI, logging, and config. The sample code for a Generic Host is up on GitHub.
A way to run long running background operations in both the generic host and in your web hosted applications. ASP.NET Core 2.1 added support for a BackgroundService base class that makes it trivial to write a long running async loop. The sample code for a Hosted Service is also up on GitHub.
Check out a simple Timed Background Task:
public Task StartAsync(CancellationToken cancellationToken)
_logger.LogInformation("Timed Background Service is starting.");
_timer = new Timer(DoWork, null, TimeSpan.Zero,
Windows Services on .NET Core
You can now host ASP.NET Core inside a Windows Service! Lots of people have been asking for this. Again, no need for IIS, and you can host whatever makes you happy. Check out Microsoft.AspNetCore.Hosting.WindowsServices on NuGet and extensive docs on how to host your own ASP.NET Core app without IIS on Windows as a Windows Service.
public static void Main(string args)
var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
var pathToContentRoot = Path.GetDirectoryName(pathToExe);
var host = WebHost.CreateDefaultBuilder(args)
IHostingStartup - Configure IWebHostBuilder with an Assembly Attribute
Simple and clean with source on GitHub as always.
Shared Source Packages
This is an interesting one you should definitely take a moment and pay attention to. It's possible to build packages that are used as helpers to share source code. We internally call these "shared source packages." These are used all over ASP.NET Core for things that should be shared BUT shouldn't be public APIs. These get used but won't end up as actual dependencies of your resulting package.
They are consumed like this in a CSPROJ. Notice the PrivateAssets attribute.
<PackageReference Include="Microsoft.Extensions.ClosedGenericMatcher.Sources" PrivateAssets="All" Version="" />
<PackageReference Include="Microsoft.Extensions.ObjectMethodExecutor.Sources" PrivateAssets="All" Version="" />
If you ever need to invoke a method on a type via reflection and that method could be async, we have a helper that we use everywhere in the ASP.NET Core code base that is highly optimized and flexible called the ObjectMethodExecutor.
The team uses this code in MVC to invoke your controller methods. They use this code in SignalR to invoke your hub methods. It handles async and sync methods. It also handles custom awaitables and F# async workflows
A small and commonly requested one. If you hate the output that dotnet run gives when you host a web application (printing out the binding information) you can use the new SuppressStatusMessages extension method.
They made it easier in 2.1 to configure options that require services. Previously, you would have had to create a type that derived from IConfigureOptions<TOptions>, now you can do it all in ConfigureServices via AddOptions<TOptions>
public void ConfigureServicdes(IServiceCollection services)
o.Path = env.WebRootPath;
IHttpContext via AddHttpContextAccessor
You likely shouldn't be digging around for IHttpContext, but lots of folks ask how to get to it and some feel it should be automatic. It's not registered by default since having it has a performance cost. However, in ASP.NET Core 2.1 a PR was put in for an extension method that makes it easy IF you want it.
So ASP.NET Core 2.1 is out and ready to go.
New features in this release include:
- SignalR – Add real-time web capabilities to your ASP.NET Core apps.
- Razor class libraries – Use Razor to build views and pages into reusable class libraries.
- Identity UI library & scaffolding – Add identity to any app and customize it to meet your needs.
- HTTPS – Enabled by default and easy to configure in production.
- Template additions to help meet some GDPR requirements – Give users control over their personal data and handle cookie consent.
- MVC functional test infrastructure – Write functional tests for your app in-memory.
- [ApiController], ActionResult<T> – Build clean and descriptive web APIs.
- IHttpClientFactory – HttpClient client as a service that you can centrally manage and configure.
- Kestrel on Sockets – Managed sockets replace libuv as Kestrel's default transport.
- Generic host builder – Generic host infrastructure decoupled from HTTP with support for DI, configuration, and logging.
- Updated SPA templates – Angular, React, and React + Redux templates have been updated to use the standard project structures and build systems for each framework (Angular CLI and create-react-app).
Check out What's New in ASP.NET Core 2.1 in the ASP.NET Core docs to learn more about these features. For a complete list of all the changes in this release, see the release notes.
Go give it a try. Follow this QuickStart and you can have a basic Web App up in 10 minutes.
Sponsor: Check out JetBrains Rider: a cross-platform .NET IDE. Edit, refactor, test and debug ASP.NET, .NET Framework, .NET Core, Xamarin or Unity applications. Learn more and download a 30-day trial!