Это решение также включает Web API резидентный с помощью Owin. Частично от here.
Вы можете создать частный метод в вас ApiController
, что не будет возвращать удаленный IP-адрес, независимо от того, как вы размещаете свой Web API:
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;
}
Ссылки: необходимые
HttpContextWrapper
- system.web. dll
RemoteEndpointMessageProperty
- System.ServiceModel.dll
OwinContext
- Microsoft.Owin.dll (у вас это будет уже, если вы используете пакет Owin)
Небольшая проблема с этим решением заключается в том, что вам нужно загружать библиотеки для всех трех случаев, когда вы фактически используете только один из них во время выполнения. Как предложено here, это можно преодолеть, используя переменные dynamic
. Вы также можете написать метод GetClientIpAddress
в качестве расширения для 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;
}
}
Теперь вы можете использовать его как это:
public class TestController : ApiController
{
[HttpPost]
[ActionName("TestRemoteIp")]
public string TestRemoteIp()
{
return Request.GetClientIpAddress();
}
}
Спасибо! Просто небольшое исправление - HttpContextWrapper следует использовать вместо HttpContext. –
Спасибо, я тоже искал это. Незначительное улучшение = класс расширения: https://gist.github.com/2653453 – MikeJansen
WebAPI по большей части очень чистый. Жаль, что такой код необходим для чего-то тривиального, как IP. – Toad