I'm Keyvan Nayyeri, a 25 years old Ph.D. student at
the Computer Science department of
the University of Texas at San Antonio.
I'm also
a Software Architect and Developer and previously held a B.Sc.
degree in Applied Mathematics.
This is my blog where I publish content about various topics specifically Programming Languages and Compilers, Software
Engineering and Programming.
One of the features that was missing from WCF 3.0 was the ability to detect client IP address in services. For a technology that is completely built on top of SOA hence a server/client mechanism where clients are an important part of the story this looked like a big lack!
There are various situations where you need to retrieve the client IP address on your service side and there is no doubt that having such a feature can be a common need and request.
However, this is a new feature added to .NET 3.5 and Windows Communication Foundation 3.5 for developers and you're now able to retrieve the client's IP address and port in your code easily.
Suppose that I have a service contract like what you see below where there is a single method to get a string argument and return another string value.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace ClientInfoSample
{
[ServiceContract]
public interface IService
{
[OperationContract]
string GetData(string value);
}
}
Here comes the implementation of this service contract with a very simple code that returns a string including the client's IP address and port.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Channels;
namespace ClientInfoSample
{
public class MyService : IService
{
public string GetData(string value)
{
OperationContext context = OperationContext.Current;
MessageProperties messageProperties = context.IncomingMessageProperties;
RemoteEndpointMessageProperty endpointProperty =
messageProperties[RemoteEndpointMessageProperty.Name]
as RemoteEndpointMessageProperty;
return string.Format("Hello {0}! Your IP address is {1} and your port is {2}",
value, endpointProperty.Address, endpointProperty.Port);
}
}
}
You simply can notice that there are a few steps to retrieve the client information from the OperationContext. First you need to get access to the current instance of the OperationContext then retrieve its IncomingMessageProperties as a MessageProperties object. The last step is to create an instance of RemoteEndpointMessageProperty by looking in the MessageProeprties collection for the name of the RemoteEndpointMessageProperty. Now RemoteEndpointMessageProperty has two separate properties to get access to the client's IP address and port.
It's worthwhile to know that behind the scenes WCF is passing the client's IP and port (along some other information) with each message as the properties for the message. This is happening for services hosted on HTTP or TCP protocols so the important point is here and you can't apply this code for other protocols.
I can self-host this service with a simple configuration file that is already generated by Visual Studio 2008 and just needs some modifications to apply new contract and service names.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<services>
<service name="ClientInfoSample.MyService" behaviorConfiguration="ClientInfoSample.MyServiceBehavior">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8731/Design_Time_Addresses/ClientInfoSample/MyService/" />
</baseAddresses>
</host>
<endpoint address ="" binding="wsHttpBinding" contract="ClientInfoSample.IService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ClientInfoSample.MyServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Hosting and running the service, I can test it quickly to get an output like what you see here:
You can download the source code sample for this post from here.
Paul Fazzino
Jan 28, 2008 11:20 AM
#
Not to bash the article however in an enterprise environment I find client IP is rarely available to an endpoint. By the time the client has jumped through their own proxy and through your own bunch of firewalls, redirectors, NAT'd, etc... the IP address becomes next to useless.
Keyvan Nayyeri
Jan 28, 2008 11:25 AM
#
Yes, you're right on proxies. I was going to mention it in the post but thought it's very obvious point, though.
But don't forget that such information is still useful and important. There are many cases when you need this information.
Shiju
Mar 05, 2008 11:57 PM
#
Hi I tried this [Detect Client IP in WCF 3.5], unfortunitly its not working in other computers. Its returning the proxy IP only. im using basicHttpBinding here.
Custom Username and Password Authentication in WCF 3.5
Apr 28, 2008 9:23 AM
#
A few days ago I wrote about a new feature in WCF 3.5 to detect client's IP address . The other new feature in .NET Framework 3.5 and Windows Communication Foundation 3.5 is the ability to write custom username and password validators in transport level
abraham
Nov 21, 2008 9:12 PM
#
Thank you for the example, this is definitely useful.
Is there some way I can detect the client's URL.
My use case involves clients within a domain accessing my web service. This could involve multiple non-contiguous IP's and the URL would be a much easier value to validate.
WCF 3.5 - Detect Client IP
Jan 15, 2009 8:24 AM
#
Following this post . As said in the post, WCF v3.5 includes easy access to the caller IP. I can see
Recuperare IP Address dentro un Web Service | hilpers
Jan 17, 2009 3:49 PM
#
Pingback from Recuperare IP Address dentro un Web Service | hilpers
How do I get the IP address of caller using HTTP/S | keyongtech
Jan 18, 2009 12:17 PM
#
Pingback from How do I get the IP address of caller using HTTP/S | keyongtech
Ricky
Jan 30, 2009 11:28 AM
#
I've been trying to implement this for client > service 1 > service2 > service1 > client, but service2 doesn't return the client ip address...any ideas on how to accomplish this?
L
Feb 26, 2009 5:08 PM
#
It always returns 127.0.0.1 (localhost)
mojtaba montazery
Aug 04, 2009 3:59 AM
#
thank keyvan,
when I am using WCF test client everything is OK , but when I am using ServiceProxy(a class library that contains generated class with svcutil.exe) and call function from IIS "OperationContext.Current" is null.
can you help me?
Felix Kollmann - flx. v2.1
Oct 09, 2009 9:22 AM
#
Bradley Ward
Jan 08, 2010 1:20 PM
#
So this is really not an answer to the question of how to get the client IP address.
Does anyone know how to get the REAL client IP address? Just like in a web application, I would like to log the xxx.xxx.xxx.xxx IP address into the log file. All I am getting using this method is an address like fe80::515c:28c9:1cc3:126b%14:51394.
Any ideas anyone?
Thanks
Ahmad Sheikholeslami
Jan 11, 2010 11:34 PM
#
Ali
Feb 13, 2010 4:05 AM
#
thank you dear keyvan.
Luke Venediger
Feb 22, 2010 3:08 AM
#
mahdi
Mar 07, 2010 9:06 AM
#
I need the ip address to log all actions by a service in server , I use net binding , in test everything is ok but i'm afraid in real condition according to above posts it won't work well
but most comments are about http binding but mine is net binding
can everybody tell me is there any difference?
Leave a Comment