I have hosted WCF 4.5 Restful service in IIS and I am trying to use
RemoteEndpointMessageProperty to get the IP address of the client who
consumes the service.
Code 1:
private string GetClientIP()
{
OperationContext context = OperationContext.Current;
MessageProperties prop = context.IncomingMessageProperties;
RemoteEndpointMessageProperty endpoint =
prop[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
string ip = endpoint.Address;
return ip;
}
Code 2:
private string GetClientIP()
{
string retIp = string.Empty;
OperationContext context = OperationContext.Current;
MessageProperties prop = context.IncomingMessageProperties;
HttpRequestMessageProperty endpointLoadBalancer =
prop[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
if (endpointLoadBalancer.Headers["X-Forwarded-For"] != null)
{
retIp = endpointLoadBalancer.Headers["X-Forwarded-For"];
}
if (string.IsNullOrEmpty(retIp))
{
RemoteEndpointMessageProperty endpoint =
prop[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
retIp = endpoint.Address;
}
return retIp;
}
However, since the WCF service is hosted in IIS behind a load balancer, the
IP address I got is always the IP of the load balancer.
Is there any way to get around this so that I can get the true IP of the
client?
OperationContext context = OperationContext.Current;
MessageProperties properties = context.IncomingMessageProperties;
RemoteEndpointMessageProperty endpoint = properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
string address = string.Empty;
//http://www.simosh.com/article/ddbggghj-get-client-ip-address-using-wcf-4-5-remoteendpointmessageproperty-in-load-balanc.html
if (properties.Keys.Contains(HttpRequestMessageProperty.Name))
{
HttpRequestMessageProperty endpointLoadBalancer = properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
if (endpointLoadBalancer != null && endpointLoadBalancer.Headers["X-Forwarded-For"] != null)
address = endpointLoadBalancer.Headers["X-Forwarded-For"];
}
if (string.IsNullOrEmpty(address))
{
address = endpoint.Address;
}
This works in case of load balancer and without it also. I had one endpoint as TCP and other one as web http for REST API.
Most Important thing is if you're using
async await
OperationContext.Current; will be null
My usage is to get Ip so used it like this before any awaitable call
var clientIpAddress = System.Web.HttpContext.Current?.Request?.UserHostAddress;
After the first await statement in your async service operation, OperationContext.Current could be null because the rest of the method body may be running on a different thread (and OperationContext does not flow between threads
So to get it you can write your code before any awaitable action
May be it'll help someone :)