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.
IHostedService
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,
TimeSpan.FromSeconds(5));
return Task.CompletedTask;
}
Fun!
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)
.UseContentRoot(pathToContentRoot)
.UseStartup<Startup>()
.Build();
host.RunAsService();
}
IHostingStartup - Configure IWebHostBuilder with an Assembly Attribute
Simple and clean with source on GitHub as always.
[assembly: HostingStartup(typeof(SampleStartups.StartupInjection))]
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="" />
ObjectMethodExecutor
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
SuppressStatusMessages
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.
WebHost.CreateDefaultBuilder(args)
.SuppressStatusMessages(true)
.UseStartup<Startup>();
AddOptions
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)
{
services.AddOptions<MyOptions>()
.Configure<IHostingEnvironment>((o,env) =>
{
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.
services.AddHttpContextAccessor();
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!
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
EF filter interceptors are not a good solution, just having been through that mess on a large project in Azure SQL Server.
This is multi-tenant where 90% of the tables/EF entities have a tenantID which must be filtered on based on the currently logged in user; and 10% of the entities/tables are shared amongst all tenants.
You should read this article on the Generic Host Builder
I think that might answer your questions about non-windows services. I have been using it for a few months and it seems to work well for me.
One other thing which I think is cool related to Razor Views being in assemblies is being able to put your MVC controllers in the same assembly with them. I doubt that part is new, but it makes a nice combo if you want to keep sections your app together. Instead of having to deal with the default Controller/View folders in a normal mvc project. Again this is probably not new but you can do that same thing with API Controllers. If you want your input/output models living next to your api controllers you can easily do that too. There are a lot of great features in .Net Core 2.1 , but being able to separate concerns so cleanly in assmeblies/projects is great. I have a project with Blazor, MVC, APIs, and Services all in separate source assemblies but ultimately running in a single .NET core host project. It is a beautiful thing. I'm loving .NET these days. These kinds of things are a great reason to use .NET core vs .NET Framework.
var webHostBuilder = WebHost.CreateDefaultBuilder(args)
.ConfigureTestServices(s => s.AddSingleton(persistence))
.UseStartup<Startup>();
I am all with you. I really like the direction .NET Core is moving on. Especially about features that you can easily extend and configure in a various ways.
The new Generic Host Builder class is a great example of this. I event actually wrote an extension for it to for configuration of Service Fabric reliable services and the greatest thing is that generic host builder provided all I need to seamlessly integrate with him.
Such things where really rare in .NET Framework.
Yes documentation on that front is lacking, but they are just using contentFiles capability: https://blog.nuget.org/20160126/nuget-contentFiles-demystified.html
Also you can see the published packages in myget: https://dotnet.myget.org/gallery/aspnetcore-dev, for example: https://dotnet.myget.org/feed/aspnetcore-dev/package/nuget/Microsoft.AspNetCore.BenchmarkRunner.Sources
Comments are closed.