Getting the Client’s IP Address in ASP.NET vNext Web Applications

I was wondering about how to get client’s IP address inside an ASP.NET vNext web application. It’s a little tricky than it should be but I finally figured it out :)
30 October 2014
4 minutes read

Related Posts

I was wondering about how to get client’s IP address inside an ASP.NET vNext web application. It’s a little tricky than it should be but I finally figured it out. So, I decided to write it down here so that anyone else can see how it’s done right now.

BIG ASS CAUTION! At the time of this writing, I am using KRE 1.0.0-beta2-10648 version. As things are moving really fast in this new world, it’s very likely that the things explained here will have been changed as you read this post. So, be aware of this and try to explore the things that are changed to figure out what are the corresponding new things.

Also, inside this post I am referencing a lot of things from ASP.NET GitHub repositories. In order to be sure that the links won’t break in the future, I’m actually referring them by getting permanent links to the files on GitHub. So, these links are actually referring the files from the latest commit at the time of this writing and they have a potential to be changed, too. Read the "Getting permanent links to files" post to figure what this actually is.

First thing to highlight here is "HTTP Features" feature (mouthful, I know :)). It’s a really exciting design if you ask me and basically, the HTTP server underneath your application will implement certain features and your application can work with these implementations. Some of the features that a server might implement can be found inside the Microsoft.AspNet.HttpFeature package. However, it’s not limited to these features only. You watch Chris Ross talking about HTTP Features on Web Camps TV to find out more about this as he gives a nice overview on HTTP Features design.

One of these HTTP features is HTTP connection feature (IHttpConnectionFeature if you want to be more specific). This feature is responsible for giving local and remote connection information for current request and this is where we can get client’s IP Address. You can try to get IHttpConnectionFeature from the HttpContext instance which you get per each request. HttpContext has two methods called GetFeature and one of them accepts a generic parameter. You can use this method to retrieve a specific feature you want to reach out to. The below Startup class shows you how you can get the client’s IP Address through the IHttpConnectionFeature.

using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using System.Threading.Tasks;
using Microsoft.AspNet.HttpFeature;

namespace RemoteIPAddressSample
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app)
        {
            app.Run(async (ctx) =>
            {
                IHttpConnectionFeature connection = ctx.GetFeature<IHttpConnectionFeature>();
                string ipAddress = connection != null
                    ? connection.RemoteIpAddress.ToString()
                    : null;

                await ctx.Response.WriteAsync("IP Address: " + ipAddress);
            });
        }
    }
}

When I hit the HTTP endpoint now, I’ll see my client’s IP address inside the response body:

image

We can even make this look nicer by refactoring this into an extension method.

public static class HttpContextExtensions
{
    public static string GetClientIPAddress(this HttpContext context)
    {
        if(context == null)
        {
            throw new ArgumentNullException("context");
        }

        IHttpConnectionFeature connection = context.GetFeature<IHttpConnectionFeature>();

        return connection != null
            ? connection.RemoteIpAddress.ToString()
            : null;
    }
}

Way better. We can now use this nice looking HttpContext extension instead:

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Run(async (ctx) =>
        {
            await ctx.Response.WriteAsync("IP Address: " + ctx.GetClientIPAddress());
        });
    }
}

One thing to mention here is that the HTTP server which your application is running on top of may choose not to implement this feature. It sounds like a very unreasonable situation as something this fundamental should be there all the time but it’s what it is. So, you should be always careful when reaching out to properties of this feature as you may get null values when you call GetFeature<T>. This rule probably applies most of the HTTP features but I wasn’t able to find any certain information whether there is a check at the very early stages of the pipeline to refuse to use the server if specific features are not implemented by the server. I’ll probably update the post when I find this out.