Detect Client IP in WCF 3.5

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:

WCF Test Client

You can download the source code sample for this post from here.

[advertisement] Axosoft OnTime 2008 is four developer tools in one: bug tracking, project wiki, feature management, and help desk. It manages your development process so developers can focus on coding. Installed or Hosted – Free Single-user license -- Free 30-day team trial.

4 Comments : 01.28.08

Feedbacks

 avatar
#1
Paul Fazzino
01.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.

admin avatar
#2
Keyvan Nayyeri
01.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.

 avatar
#3
Shiju
03.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.

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

Leave a Comment