128

Hello I need get client IP that request some method in web api, I have tried to use this code from here but it always returns server local IP, how to get in correct way ?

HttpContext.Current.Request.UserHostAddress;

from other questions:

public static class HttpRequestMessageExtensions
    {
        private const string HttpContext = "MS_HttpContext";
        private const string RemoteEndpointMessage = "System.ServiceModel.Channels.RemoteEndpointMessageProperty";

        public static string GetClientIpAddress(this HttpRequestMessage request)
        {
            if (request.Properties.ContainsKey(HttpContext))
            {
                dynamic ctx = request.Properties[HttpContext];
                if (ctx != null)
                {
                    return ctx.Request.UserHostAddress;
                }
            }

            if (request.Properties.ContainsKey(RemoteEndpointMessage))
            {
                dynamic remoteEndpoint = request.Properties[RemoteEndpointMessage];
                if (remoteEndpoint != null)
                {
                    return remoteEndpoint.Address;
                }
            }

            return null;
        }
    }
Steve Powell
  • 23,886
  • 8
  • 40
  • 42
Arbejdsglæde
  • 13,141
  • 22
  • 75
  • 142

9 Answers9

139

Following link might help you. Here's code from the following link.

reference : getting-the-client-ip-via-asp-net-web-api

using System.Net.Http;
using System.ServiceModel.Channels;
using System.Web;
using System.Web.Http;


namespace Trikks.Controllers.Api
{
    public class IpController : ApiController
    {
          public string GetIp()
          {
                return GetClientIp();
          }

          private string GetClientIp(HttpRequestMessage request = null)
          {
                request = request ?? Request;

                if (request.Properties.ContainsKey("MS_HttpContext"))
                {
                      return   ((HttpContextWrapper)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
                }
                else if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
                {
                     RemoteEndpointMessageProperty prop = (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name];
                     return prop.Address;
                }
                else if (HttpContext.Current != null)
                {
                    return HttpContext.Current.Request.UserHostAddress;
                }
                else
                {
                      return null;
                }
           }
     }
}

Another way of doing this is below.

reference: how-to-access-the-client-s-ip-address

For web hosted version

string clientAddress = HttpContext.Current.Request.UserHostAddress;

For self hosted

object property;
        Request.Properties.TryGetValue(typeof(RemoteEndpointMessageProperty).FullName, out property);
        RemoteEndpointMessageProperty remoteProperty = property as RemoteEndpointMessageProperty;
Eric Herlitz
  • 23,976
  • 26
  • 110
  • 154
Jalpesh Vadgama
  • 13,062
  • 19
  • 69
  • 93
76

With Web API 2.2: Request.GetOwinContext().Request.RemoteIpAddress

Ben Wilde
  • 5,304
  • 2
  • 36
  • 35
20

Try to get the Ip using

ip = HttpContext.Current != null ? HttpContext.Current.Request.UserHostAddress : "";
user1587439
  • 1,659
  • 1
  • 12
  • 8
10

If you're self-hosting with Asp.Net 2.1 using the OWIN Self-host NuGet package you can use the following code:

 private string getClientIp(HttpRequestMessage request = null)
    {
        if (request == null)
        {
            return null;
        }

        if (request.Properties.ContainsKey("MS_OwinContext"))
        {
            return ((OwinContext) request.Properties["MS_OwinContext"]).Request.RemoteIpAddress;
        }
        return null;
    }
CoryC
  • 650
  • 6
  • 6
10

I think this is the most clear solution, using an extension method:

public static class HttpRequestMessageExtensions
{
    private const string HttpContext = "MS_HttpContext";
    private const string RemoteEndpointMessage = "System.ServiceModel.Channels.RemoteEndpointMessageProperty";

    public static string GetClientIpAddress(this HttpRequestMessage request)
    {
        if (request.Properties.ContainsKey(HttpContext))
        {
            dynamic ctx = request.Properties[HttpContext];
            if (ctx != null)
            {
                return ctx.Request.UserHostAddress;
            }
        }

        if (request.Properties.ContainsKey(RemoteEndpointMessage))
        {
            dynamic remoteEndpoint = request.Properties[RemoteEndpointMessage];
            if (remoteEndpoint != null)
            {
                return remoteEndpoint.Address;
            }
        }

        return null;
    }
}

So just use it like:

var ipAddress = request.GetClientIpAddress();

We use this in our projects.

Source/Reference: Retrieving the client’s IP address in ASP.NET Web API

Vasil Popov
  • 1,126
  • 13
  • 22
10

Replying to this 4 year old post, because this seems overcomplicated to me, at least if you're hosting on IIS.

Here's how I solved it:

using System;
using System.Net;
using System.Web;
using System.Web.Http;
...
[HttpPost]
[Route("ContactForm")]
public IHttpActionResult PostContactForm([FromBody] ContactForm contactForm)
    {
        var hostname = HttpContext.Current.Request.UserHostAddress;
        IPAddress ipAddress = IPAddress.Parse(hostname);
        IPHostEntry ipHostEntry = Dns.GetHostEntry(ipAddress);
        ...

Unlike OP, this gives me the client IP and client hostname, not the server. Perhaps they've fixed the bug since then?

Liam
  • 25,247
  • 27
  • 110
  • 174
Scott R. Frost
  • 1,955
  • 1
  • 20
  • 25
5

It's better to cast it to HttpContextBase, this way you can mock and test it more easily

public string GetUserIp(HttpRequestMessage request)
{
    if (request.Properties.ContainsKey("MS_HttpContext"))
    {
        var ctx = request.Properties["MS_HttpContext"] as HttpContextBase;
        if (ctx != null)
        {
            return ctx.Request.UserHostAddress;
        }
    }

    return null;
}
Patrick Hofman
  • 148,824
  • 21
  • 237
  • 306
  • 1
    I googled around and others seem to concur with this (cast to HttpContextBase instead of HttpContextWrapper because HttpContextBase is easier to mock.) – Dave Clausen Jul 19 '16 at 18:03
2

My solution is similar to user1587439's answer, but works directly on the controller's instance (instead of accessing HttpContext.Current).

In the 'Watch' window, I saw that this.RequestContext.WebRequest contains the 'UserHostAddress' property, but since it relies on the WebHostHttpRequestContext type (which is internal to the 'System.Web.Http' assembly) - I wasn't able to access it directly, so I used reflection to directly access it:

string hostAddress = ((System.Web.HttpRequestWrapper)this.RequestContext.GetType().Assembly.GetType("System.Web.Http.WebHost.WebHostHttpRequestContext").GetProperty("WebRequest").GetMethod.Invoke(this.RequestContext, null)).UserHostAddress;

I'm not saying it's the best solution. using reflection may cause issues in the future in case of framework upgrade (due to name changes), but for my needs it's perfect

Nissim
  • 6,106
  • 5
  • 47
  • 72
2
string userRequest = System.Web.HttpContext.Current.Request.UserHostAddress;

This works on me.

System.Web.HttpContext.Current.Request.UserHostName; this one return me the same return I get from the UserHostAddress.

Tasos K.
  • 7,831
  • 7
  • 41
  • 61
Robert Tan
  • 31
  • 4