回答:
それを行うことは可能ですが、それほど発見することはできません。受信したリクエストからプロパティバッグを使用する必要があり、アクセスする必要があるプロパティは、IIS(Webホスト)またはセルフホストでWeb APIを使用しているかどうかによって異なります。以下のコードは、これを行う方法を示しています。
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;
}
RemoteEndpointMessageProperty
中、クラスSystem.ServiceModel.Channels
、名前空間のSystem.ServiceModel.dll
アセンブリ?それはWCFに属するアセンブリではありませんか?
このソリューションは、Owinを使用してセルフホストされたWeb APIもカバーしています。部分的にはここから。
ApiController
Web APIをホストする方法に関係なく、リモートIPアドレスを返すプライベートメソッドを作成できます。
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.dllRemoteEndpointMessageProperty
-System.ServiceModel.dllOwinContext
-Microsoft.Owin.dll(Owinパッケージを使用している場合は、すでにインストールされています)このソリューションの小さな問題は、実行時に実際にライブラリの1つだけを使用する場合に、3つすべてのケースでライブラリをロードする必要があることです。ここで提案されているように、これは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();
}
}
using System.Net.Http;
あなたが拡張しているのであなたはラインが必要HttpRequestMessage
です。あなたがSystem.Net.Http
非常に疑わしい名前空間で拡張を定義しているのでない限り。ただし、IDEまたは生産性向上ツールによって自動的に追加されるため、必須かどうかはわかりません。どう思いますか?
上記の回答では、プロパティをHttpContextまたはHttpContextWrapperにキャストできるようにSystem.Webへの参照が必要です。参照が必要ない場合は、ダイナミックを使用してIPを取得できます。
var host = ((dynamic)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
carlosfigueiraが提供するソリューションは機能しますが、タイプセーフなワンライナーの方が優れています。アクションメソッドにusing System.Web
then thenアクセスHttpContext.Current.Request.UserHostAddress
を追加します。
HttpContext.Current
、タスクパイプライン全体で正しく保持されないため、Web APIでは信頼できません。すべてのリクエスト処理は非同期であるためです。HttpContext.Current
Web APIコードを作成するときは、ほとんど常に回避する必要があります。
SynchronizationContext
、タスク間で正しくフローされている場合は必ずしも直接ではありません)。これに関する最大の問題は、サービスコードがセルフホストされる可能性があるかどうか(テストなど)です- HttpContext.Current
純粋にAsp.Net構造であり、セルフホストする場合は存在しません。
NullReferenceException
、スレッド(たとえば、最新のWeb APIコードでは非常に一般的なタスク待機者)またはセルフホストコンテキストから使用すると、デバッグが困難になります。少なくとも他のほとんどの答えは単に返されnull
ます。