Uzak ana bilgisayarın IP adresini alın


136

ASP.NET'te System.Web.HttpRequest, ServerVariablesbize REMOTE_ADDRözellik değerinden IP adresini sağlayabilen özelliği içeren bir sınıf vardır .

Ancak, ASP.NET Web API'sından uzak ana bilgisayarın IP adresini almanın benzer bir yolunu bulamadım.

İstekte bulunan uzak ana bilgisayarın IP adresini nasıl alabilirim?

Yanıtlar:


189

Bunu yapmak mümkündür, ancak çok keşfedilemez - gelen isteği gelen özellik çantasını kullanmanız gerekir ve erişmeniz gereken özellik, Web API'sını IIS (webhosted) altında mı yoksa kendi kendini barındırıyor mu kullandığınıza bağlıdır. Aşağıdaki kod bunun nasıl yapılabileceğini göstermektedir.

private string GetClientIp(HttpRequestMessage request)
{
    if (request.Properties.ContainsKey("MS_HttpContext"))
    {
        return ((HttpContextWrapper)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
    }

    if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
    {
        RemoteEndpointMessageProperty prop;
        prop = (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name];
        return prop.Address;
    }

    return null;
}

4
Teşekkürler, ben de bunu arıyordum. Küçük gelişme = uzatma sınıfı: gist.github.com/2653453
MikeJansen

28
WebAPI çoğunlukla çok temiz. IP gibi önemsiz bir şey için böyle bir kodun gerekli olması çok yazık.
Kurbağa

2
Mi RemoteEndpointMessagePropertysınıf System.ServiceModel.Channels, ad System.ServiceModel.dllmontaj? Bu WCF'ye ait bir meclis değil mi?
Slauma

4
@Slauma, evet, öyleler. ASP.NET Web API (şu anda) kendi kendine barındırılan ve web'de barındırılan iki "tat" halinde uygulanmaktadır. Web'de barındırılan sürüm ASP.NET'in üzerine uygulanırken, kendinden barındırılan sürüm bir WCF dinleyicisinin üzerine uygulanır. Platformun (ASP.NET Web API) kendisinin barındırma-agnostik olduğuna dikkat edin, bu nedenle birinin gelecekte farklı bir barındırma uygulayacağı ve ana bilgisayarın bu özelliği (uzak uç nokta) farklı bir şekilde ortaya çıkaracağı mümkündür.
carlosfigueira

3
Ne yazık ki, Owin kullanarak kendi kendine barındırıyorsanız (Web API 2 için önerildiği gibi) bu çalışmaz. Orada başka bir ihtiyaç ...
Nikolai Samteladze

74

Bu çözüm, Owin kullanılarak barındırılan Web API'sını da kapsar. Kısmen buradan .

ApiControllerWeb API'nizi nasıl barındırırsanız barındırın, uzak IP adresini döndürecek özel bir yöntem oluşturabilirsiniz :

 private const string HttpContext = "MS_HttpContext";
 private const string RemoteEndpointMessage =
     "System.ServiceModel.Channels.RemoteEndpointMessageProperty";
 private const string OwinContext = "MS_OwinContext";

 private string GetClientIp(HttpRequestMessage request)
 {
       // Web-hosting
       if (request.Properties.ContainsKey(HttpContext ))
       {
            HttpContextWrapper ctx = 
                (HttpContextWrapper)request.Properties[HttpContext];
            if (ctx != null)
            {
                return ctx.Request.UserHostAddress;
            }
       }

       // Self-hosting
       if (request.Properties.ContainsKey(RemoteEndpointMessage))
       {
            RemoteEndpointMessageProperty remoteEndpoint =
                (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessage];
            if (remoteEndpoint != null)
            {
                return remoteEndpoint.Address;
            }
        }

       // Self-hosting using Owin
       if (request.Properties.ContainsKey(OwinContext))
       {
           OwinContext owinContext = (OwinContext)request.Properties[OwinContext];
           if (owinContext != null)
           {
               return owinContext.Request.RemoteIpAddress;
           }
       }

        return null;
 }

Gerekli kaynaklar:

  • HttpContextWrapper - System.Web.dll
  • RemoteEndpointMessageProperty - System.ServiceModel.dll
  • OwinContext - Microsoft.Owin.dll (Owin paketini kullanırsanız zaten sahip olacaksınız)

Bu çözümle ilgili küçük bir sorun, çalışma zamanı sırasında bunlardan yalnızca birini kullanacağınız zaman, tüm 3 durum için kütüphaneleri yüklemeniz gerektiğidir. Önerildiği gibi burada , bu kullanarak aşılabilir dynamicdeğişkenleri. GetClientIpAddressYöntemini bir uzantısı olarak da yazabilirsiniz HttpRequestMethod.

using System.Net.Http;

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

    public static string GetClientIpAddress(this HttpRequestMessage request)
    {
       // Web-hosting. Needs reference to System.Web.dll
       if (request.Properties.ContainsKey(HttpContext))
       {
           dynamic ctx = request.Properties[HttpContext];
           if (ctx != null)
           {
               return ctx.Request.UserHostAddress;
           }
       }

       // Self-hosting. Needs reference to System.ServiceModel.dll. 
       if (request.Properties.ContainsKey(RemoteEndpointMessage))
       {
            dynamic remoteEndpoint = request.Properties[RemoteEndpointMessage];
            if (remoteEndpoint != null)
            {
                return remoteEndpoint.Address;
            }
        }

       // Self-hosting using Owin. Needs reference to Microsoft.Owin.dll. 
       if (request.Properties.ContainsKey(OwinContext))
       {
           dynamic owinContext = request.Properties[OwinContext];
           if (owinContext != null)
           {
               return owinContext.Request.RemoteIpAddress;
           }
       }

        return null;
    }
}

Şimdi şöyle kullanabilirsiniz:

public class TestController : ApiController
{
    [HttpPost]
    [ActionName("TestRemoteIp")]
    public string TestRemoteIp()
    {
        return Request.GetClientIpAddress();
    }
}

1
Bu çözüm çalışmak için bu ad alanı "System.Net.Http" kullanmalıdır. Bu, Assembly System.Web.Http.dll, v5.2.2.0 üzerinde bir sınıf adı olduğundan.
Wagner Bertolini Junior

@WagnerBertolini, doğru, sizin using System.Net.Http;satır gerekir çünkü uzanan HttpRequestMessage. Uzantınızı System.Net.Httpad alanında tanımlayamazsanız, bu çok tartışmalıdır. Yine de gerekli olduğundan emin değilsiniz, çünkü herhangi bir IDE veya verimlilik aracı tarafından otomatik olarak eklenecektir. Ne düşünüyorsun?
Nikolai Samteladze

Burada bir işi bitirmek için acelem vardı ve ne yapı hatası oluyor görmek için 20 dakikadan fazla sürdü. Sadece kodu kopyaladım ve bunun için bir sınıf oluşturdum, derleme yaparken yöntemleri göstermiyordu, VS'de "tanımlamaya git" i kullandığımda beni sınıfıma götürdü ve ben ne olup bittiğini anlamadım, ben diğer sınıfı buldum. Uzantılar oldukça yeni bir özelliktir ve her zaman kullanılmaz, çünkü bu kez tasarruf etmenin iyi bir fikir olacağını düşünüyorum.
Wagner Bertolini Junior

1
Request.GetOwinContext () Request.RemoteIpAddress. Owin kullanırken, tıpkı Owin içeriği almak için OwinHttpRequestMessageExtensions kullanabilirsiniz
Stef Heyenrath

1
Aslında var ctx = request.Properties [MsHttpContext] HttpContextWrapper olarak olmalıdır; Eğer yayın yaparsanız,
null'u

31

Gerçekten bir astar istiyorsanız ve Web API'sını kendi kendine barındırmayı planlamıyorsanız:

((System.Web.HttpContextWrapper)Request.Properties["MS_HttpContext"]).Request.UserHostAddress;

13

Yukarıdaki yanıtlar özelliği HttpContext veya HttpContextWrapper öğesine yayınlayabilmek için System.Web'e başvuru gerektirir. Referansı istemiyorsanız, bir dinamik kullanarak ip alabilirsiniz:

var host = ((dynamic)request.Properties["MS_HttpContext"]).Request.UserHostAddress;

-1

Carlosfigueira tarafından sağlanan çözüm işe yarıyor, ancak tip güvenli tek katmanlar daha iyi: Eylem yönteminize using System.Weberişim HttpContext.Current.Request.UserHostAddressekleyin.


26
-1 Bu HttpContext.Currentgörev web hattı boyunca doğru bir şekilde devam etmediği için web API'sinde güvenilemez ; çünkü tüm isteklerin işlenmesi zaman uyumsuzdur. HttpContext.CurrentWeb API kodu yazılırken neredeyse her zaman kaçınılmalıdır.
Andras Zoltan

@Andras, HttpContext.Current kullanmanın neden kötü olduğunu daha fazla ayrıntı bilmek istiyorum, bunun için değerli bir kaynak biliyor musunuz?
cuongle

13
Merhaba @CuongLe; aslında - diş çekme sorunu bir sorun olabilirken ( SynchronizationContextgörevler arasında doğru bir şekilde akıyorsa her zaman doğrudan olmasa da ); bununla ilgili en büyük sorun, servis kodunuzun kendiliğinden barındırılabilme olasılığı varsa (örneğin test etme) - HttpContext.Currenttamamen Asp.Net yapısıdır ve kendi kendine barındırdığınızda mevcut değildir.
Andras Zoltan

Tip güvenliği her şey değildir. Bu kod, NullReferenceExceptionbir iş parçacığından (örneğin, modern Web API kodunda çok yaygın olan bir görev bekleyen) veya kendi kendine barındırılan bir bağlamda kullanıldığında hata ayıklaması zor bir hata atar. Diğer cevapların en azından çoğu geri dönecektir null.
Aaronaught
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.