Sooner or later, we need to know the status of our application, external services it uses and all other parts important for our application to work properly. For example, an application may have a health check for its database connection to ensure that the connection is still alive and working properly. If the database connection fails, the health check system can be configured to report the problem to interested parties.
ASP.NET provides a built-in health check system that can be used to monitor these parts. Health checks are exposed by an application as HTTP endpoints, where the basic use case is to check the ability to a process request.
It is important to identify which parts of application we want to monitor because ASP.NET provides different NuGet packages for specific components (e.g., to check SQL Server database, we need to include a package reference to the AspNetCore.HealthChecks.SqlServer). Also, the whole purpose of health checks is to be quick ping, not to overload critical infrastructure.
The health check behavior in ASP.NET is highly configurable, and developers can customize many aspects of its behavior. For example, we can customize the type of HTTP response that is send for different health check results (by default, we have healthy, degraded, unhealthy).
The basic usage is very simple, we just need to add a few lines of code to the Program class;
var builder = WebApplication.CreateBuilder(args);
   builder.Services.AddHealthChecks();
...
     app.MapHealthChecks("/healthcheck");
This will register health check services and map the health endpoint at specified URL. By default, an application is considered healthy if it can respond from health endpoint URL. The default response is plaintext, but it can be customized.
Now we will see how to check the Oracle database health status;
builder.Services.AddHealthChecks()
     .AddOracle(
       Configuration.GetConnectionString("OracleDB"),
       healthQuery: "SELECT * from v$version",
       name: "oracle",
       null,
       tags: new string[] { "db", "oracle" },
       TimeSpan.FromSeconds(5)
       );
First, we need to add AspNetCore.HealthChecks. The Oracle NuGet package, which provide us with a specific method for Oracle health checks. Then we use the AddOracle() method with its parameters like connection string to database, query to execute, name for this health check, timeout and so on.
For database health checks, it is important to choose a query that is very simple and runs fast because we don’t want to overload the database unnecessarily. The goal is to make a successful connection to the database.
If we want to allow anonymous access to our health endpoint, there is a neat method that allows exactly that - AllowAnonymous(). Usage example;
app.UseEndpoints(endpoints =>
   {
       endpoints.MapHealthChecks("/healthcheck").AllowAnonymous();
   });
On the other hand, if we want to allow only authorized access, we can use the RequireAuthorization method, which will run the authorization middleware on the out health endpoint.
app.UseEndpoints(endpoints =>
   {
       endpoints.MapHealthChecks("/healthcheck"). RequireAuthorization();
   });
This method can be overloaded to specify custom authorization policies depending on our needs.
Also, we can restrict access to the health check endpoint for permitted hosts or ports. RequireHost is the method to use for those scenarios.
Usage example;
app.UseEndpoints(endpoints =>
   {
       endpoints.MapHealthChecks("/healthcheck").RequireHost($"*:{Configuration.GetValue["HealthCheckAllowedPort"]}");
   });
We have options to configure behavior of health checks to suit our needs. Options like caching, custom response writer and custom HTTP status code that will be used in response.
Usage example;
endpoints.MapHealthChecks("/healthcheck", new HealthCheckOptions() {
         ResultStatusCodes =
           {
                       [HealthStatus.Healthy] = StatusCodes.Status200OK,
                       [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
                   },
          ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse,
         AllowCachingResponses = false,
       });
In the above example, two status codes are used- the response is formatted using UIResponseWriter provided by a separate NuGet library, and response caching is disabled. As we can see, these options provide us with the flexibility to meet our demands.
In conclusion, the health check system in ASP.NET Core provides a convenient and flexible way for developers to monitor the health of their applications and take appropriate action when issues are detected. The basic usage is very simple and easy to customize, with very detailed documentation online.
By using this feature, developers can ensure that their applications are stable and perform well in a production environment.