Retrieving the client’s IP address in ASP.NET Web API

One of the common tasks, for logging or authorization purposes, is to obtain the IP address of the client accessing your Web API.

There are different ways to achieve this depending on whether you are web hosting (through HttpContext) or whether you are self hosting (through WCF’s RemoteEndpointMessageProperty).

To avoid the redundant code, we can unify those approaches under a single extension method, which you can use across all your projects.

Obtaining the client IP in ASP.NET Web API web host

To get the IP from the incoming request in the web host scenarios, we have to get hold of HttpContext. This is done very easily, through the Ms_HttpContext request property key.

Of course this requires that you reference System.Web as that’s where HttpContextWrapper resides.

Obtaining the client IP in ASP.NET Web API self host

In self host scenarios, you can access client information through RemoteEndpointMessageProperty, which, similarly to web host, is stored in the properties of the incoming HttpRequestMessage. The property is added to each incoming message to a WCF service through both the HTTP and TCP transports. Since Web API self host uses WCF core, it’s there for our API host too.

In this case, we look for the property key “RemoteEndpointMessageProperty.Name” which simply is the fully qualified name – “System.ServceModel.Channels.RemoteEndpointMessageProperty”.

Since we cast to RemoteEndpointMessageProperty we need to reference System.ServiceModel.dll, as that’s where this class is declared. You can read up more on MSDN.

Unifying the two approaches

Of course it’s not very convenient to have two separate bits of code that you have to drag along to each type of project (self vs web host). We can easily wrap both approaches in a single extension method, and hang it off HttpRequestMethod.

Since we don’t want self host to reference System.Web, and we don’t want web host to unnecessarily reference System.ServiceModel, we could use dynamic to avoid strong typing and defer the type evaluation until runtime (by-pass compile time type check). Since we deal with, effectively, an if-else scenario here, only one code path will ever be used in each type of hosting anyway.

Here’s the complete solution:

You can now safely use this extension in each type of Web API project, and not worry about having to reference unnecessary DLLs just to make the code compile (as we would have to, if we wouldn’t use dynamic).

It’s important to mention that you have to reference System.ServiceModel in self hosted projects, as it’s not included by default (contrary to System.Web always being there for web host).

You can now use this anywhere, where you have access to the current HttpRequestMessage. For example:

If you use WebApiContrib (and you should!), I have added this extension method there too.

Be Sociable, Share!

  • Pingback: Dew Drop – May 23, 2013 (#1,553) | Alvin Ashcraft's Morning Dew()

  • Jacob Reimers

    If the client is connecting through a proxy, you may want to check for the X-Forwarded-For header – http://en.wikipedia.org/wiki/X-Forwarded-For

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1363()

  • Tim O’Reilly

    Great post! Thank you so much!!!

  • Pingback: Article Soup for May 31st 2013 - I am Levi()

  • Andy Cohen

    I didn’t know that HttpContext was exposed that way in Web Api. Nice find and elegant solution. Thanks.

  • Pingback: Retrieving the client's IP address in ASP.NET W...()

  • Pingback: Retrieving the client’s IP address in ASP.NET Web API | Danny Acuna's Blog()

  • Nk

    Thank,

    For unit testing I am trying to utilize your code. where I need to pass HttpRequestMessage to retrieve ClientIp.

    Yes I am able to set HttpContext in MS_HttpContext property but not able to Request.UserHostAddress which is required to test your method.

    Is it possible to do it using HttpContextWrapper?
    If yes then please let me know..

  • Vedran Mandić

    Great, thanks so much!

  • isha priya

    hi can u host the source code for this and whether it will work for clients beyond NATs and firewall and get each client’s internal ip address?

  • Bra

    I have a validation handler ( config.MessageHandlers.Add(new ValidationHandler()); ) defined and in there I work with the HttpRequestMessage object but it doesn’t contain the IP address in any form… any suggestions please?

  • Mario Santamaria

    add this for owin self host:

    if (request.Properties.ContainsKey(“MS_OwinContext”))
    {
    dynamic owinContext = request.Properties[“MS_OwinContext”];
    return owinContext.Request.RemoteIpAddress;
    }

  • Amin Saadati

    very nice. thank you Filip W.