Building an interactive service with .NET Core 2.1
Exploring whats new with .NET Core 2.1 whilst also exploring how to make services a bit friendlier
TL;DR: .NET Core 2.1 makes Windows Services really straight forward, and integrating other parts of .NET Core technology is very straight-forward. Go look at the sample application.
It started with a tweet (that I can’t find…) And then it lay, festering, for a while. An itch unscratched. How to make windows service configuration/status available via http? Of course I actually already possess all of the tools necessary to do this. I’m just a bit short of time (and in truth some motivation) to work out how to get all those disparate pieces working together.
And then there was another tweet, or more accurately a blizzards of tweets:
Ok tweeting about some hidden gems in the release that people may not know about. #aspnetcore #dotentcore
— David Fowler (@davidfowl) June 6, 2018
And in there, close to the top, were these two:
Next, Windows services now work on .NET Core https://t.co/RFSCY4JyyY. The docs are being updated https://t.co/8w6FQw72og (it still says .NET Framework only)
— David Fowler (@davidfowl) June 6, 2018
Next, IHostedService. A way to run long running background operations in both the generic host and in your web hosted applications. https://t.co/cR2rB8SZHa. 2.1 added support for a BackgroundService base class that makes it trivial to write a long running async loop.
— David Fowler (@davidfowl) June 6, 2018
I might just have found my motivation…
.NET Core 2.1 was announced at the end of May this year, and it is the kind of step change that .NET Fx (Framework) 2 was to .NET Fx 1.1. To me at least it moves Core from being something I want to work with, to something that I can happily and easily work with day in and day out. Motivation sorted I got on with it (kind of…)
The sample I slapped together is available on GitHub, and details of links etc are available in the individual commits:
- Host ASP.NET Core in a Windows Service - Running a .NET Core application as a service. It’s worth noting that to get the sample to work at this point I needed to fix versions to
2.1.0
, and I needed an extrausing
statement:Microsoft.AspNetCore.Hosting.WindowsServices
- Adding Autofac was based on the Autofac ASP.NET Core and .NET Core documentation, as well as the ASP.NET Core and Generic Host Builder Examples
- Adding the hosted service (essentially the service that runs in the background) was based on docs.microsoft
- Going back to the RabbitMq Tutorials really helped a huge amount (internally at work we have a very sophisticated package that works nicely with RabbitMq and Autofac, but means I’ve completely forgotten how to RabbitMq…)
- Finally setting up App-Metrics was based on the getting started tutorial, and ASP.NET Core docs and quick start
The real work came in figuring out how to get the (now badly named) TimedHostedService
into the Home Controller. Initially I simply had DI inject an instance. But it quickly became apparent that this wasn’t the instance that the Framework had setup to run in the background.
Looking in Startup I needed to work out what .AddHostedService<>()
was doing. Rather nicely .NET Core is open source, so this is very straight forward. And it turns out the method is just registering my type as a transient type, that specifically implements IHostedService
. Taking this knowledge I can now dump that call to register the hosted service, and substitute it with a new registration (in Autofac) that tells the DI there should only be one instance of the class, and that it implements multiple interfaces. As a friend says Job Jobbed.
In truth if you’re putting something in to production you probably want to tidy this up, but the basic concept is there. Are there other changes you might want to make? Definitely:
- To get ASP.NET MVC working nicely I brought along a lot of extras, that’s not nice really. Can they be cut down? How about using something like Nancy Fx?
- The view to get the service status and button in front of the user isn’t included in the executable, which could lead to issues, perhaps those could be retrieved from Resources, or elsewhere?
- The DI setup is gnarly, that can probably be cleaned up as well
But I’m going to leave these inspirations for another time.