To allow for varying implementations we can start by defining the IStatus interface
Two of these fields are very simple expression bodies:
The build version can be incremented automatically via various build processes or incremented manually as needed.
Two more pull from IHostEnvironment, which can be injected into our constructor. (Note that this is different than IHostingEnvironment, which is obsolete)
Last is the build date data. There are a few common ways of obtaining this data, including PE header data (now obsolete due to deterministic builds) or using a build script to write the date to resource file. In our case we're going to use a naive but simple method to look at the most recent time the current assembly was written.
This approach does have one or two shortcomings, namely that the LastWriteTime could change when files move around. For our purposes of easy confirmation that the deployed code has changed this is acceptable but this may be a problem in other situations.
The other concern is around reading the file system unnecessarily. This can be alleviated by setting the Status implementation as a singleton.
Finally the status object can be injected to our controller and returned as an ObjectResult.
Put all together this returns the following JSON:
When integrated with advanced build pipeline processes, even more data can be exposed via this process as well.
Now we can easily check if the latest version of code is running, which can help save considerable time for troubleshooting and bug reports.