Skip to content

How to Create Health Checks in ASP.NET Core

Health Checks in ASP.NET CoreIf you’re using a load balancer in front of your ASP.NET Core application you will need to provide it a route where it can verify that your application is still running.  Here’s an overview of how you can implement implement Health Checks in ASP.NET Core.

Health Checks in ASP.NET Core

If you’re using ASP.NET Core MVC, you might first think to just create a controller and action and provide that route as the health check for your load balancer.

However there are alternative ways to accomplish this with middleware.

Basic Middleware

At the very basic level, we can create a middleware high in the pipeline that is checking the request path and if /hc, return a 200 status code along with content “UP”.  Here’s our Startup’s Configure method.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.Use(async (context, func) =>
{
if (context.Request.Path.Value == "/hc")
{
context.Response.StatusCode = 200;
context.Response.ContentLength = 2;
await context.Response.WriteAsync("UP");
}
else
{
await func.Invoke();
}
});
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}
view raw startup.cs hosted with ❤ by GitHub

Checking Services

At a minimum we are confirming that ASP.NET Core is running, but often times we are using databases and other external services that our web application needs to access.  If our application cannot connect to these external services, do we want them to remain in the load balancer pool?  If not, then we can add some various checks and return a 200 if everything is successful.

app.Use(async (context, func) =>
{
if (context.Request.Path.Value == "/hc")
{
try
{
using (var db = new SqlConnection("Database=Oops"))
{
await db.OpenAsync();
db.Close();
}
context.Response.StatusCode = 200;
context.Response.ContentLength = 2;
await context.Response.WriteAsync("UP");
}
catch (SqlException)
{
context.Response.StatusCode = 400;
context.Response.ContentLength = 20;
await context.Response.WriteAsync("SQL Connection Error");
}
}
else
{
await func.Invoke();
}
});
view raw checkdb.cs hosted with ❤ by GitHub

Refactor

Be honest, having that database code in there is pretty awful.  Let’s move this out into it’s own class and add an extension method onto IApplicationBuilder.

public class HealthCheckMiddleware
{
private readonly RequestDelegate _next;
private readonly string _path;
public HealthCheckMiddleware(RequestDelegate next, string path)
{
_next = next;
_path = path;
}
public async Task InvokeAsync(HttpContext context)
{
if (context.Request.Path.Value == _path)
{
try
{
using (var db = new SqlConnection("Database=Oops"))
{
await db.OpenAsync();
db.Close();
}
context.Response.StatusCode = 200;
context.Response.ContentLength = 2;
await context.Response.WriteAsync("UP");
}
catch (SqlException)
{
context.Response.StatusCode = 400;
context.Response.ContentLength = 20;
await context.Response.WriteAsync("SQL Connection Error");
}
}
else
{
await this._next(context);
}
}
}
public static class HealthCheckMiddlewareExtensions
{
public static IApplicationBuilder UseHealthCheck(this IApplicationBuilder builder, string path)
{
return builder.UseMiddleware<HealthCheckMiddleware>(path);
}
}
view raw middleware.cs hosted with ❤ by GitHub

Now from our Configure() method we can just call the extension method.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHealthCheck("/hc");
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}
view raw extension.cs hosted with ❤ by GitHub

ASP.NET Core 2.2

As of this writing, ASP.NET Core 2.2 has a plan for built in health checks.  This post will be updated accordingly when it is released.

Further

Hopefully this gets you the idea of passing configuration data (path) to the middleware.  You can take this much further depending on your needs.

Are you using another solution for handling health checks?  Let me know in the comments or on Twitter.

Learn more about Software Architecture & Design.
Join thousands of developers getting weekly updates to increase your understanding of software architecture and design concepts.


Leave a Reply

Your email address will not be published. Required fields are marked *