Technology Corner

Home » DotNet » WCF

Category Archives: WCF

Follow Technology Corner on WordPress.com

How to pass behaviour in WCF DataContract to client application?

Problem Statement: You want to override ToString or any method of DataContract class and method logic should be propagate to client application.

Resolution:

WCF doesn’t transfer any behavior of data contract to client side by default.
I am taking here two approaches to communicate to WCF service; through proxy class generated by Visual studio and other is creating channel instance using ChannelFactory class.In later approach, DataContract should be shared between server and clients.

Say you have data contract MarketPrice.

[DataContract]
public class MarketPrice
{
[DataMember]
public string Symbol { get; set; }

[DataMember]
public double Price { get; set; }

[OperationContract]
public override string ToString()
{
return string.Format("Symbol:{0} Price:{1}", Symbol, Price);
}
}

Approach 1:

Behavior of ToString() method will not propagate to client proxy. You will have to change in generated code like below:

wcf proxy

Approach 2:

You can read about how to create api or manual proxy class using channel factory here.

Service contract and Data contract are in shared library which is shared across server and client applications. Service contract implementation is still in service side.

Advertisements

Implement Role based security using Windows Groups in WCF

This is third blog on security concept in WCF. You can read previous posts:

Something about Security in WCF- I

Implement windows authentication and security in WCF Service

Today I’ll describe how we can implement role based authorization using Windows Group. In this case you will not need to maintain any information in database because roles are managing through windows group.

Step1: Create Windows Group

MarketServiceSuperUser in “Windows Users and Groups” in control panel. This group will be treated as roles in application.

image

Step2: Add users to windows Group. In this case user will be member of this group.

image

image

 

Step 3: Implement Role based security in Service side.

The principal in .NET is any object that implements the IPrincipal interface, defined in the System.Security.Principal namespace:

public interface IPrincipal
{
IIdentity Identity

{get;}

bool IsInRole(string role);

}

The IsInRole() method simply returns true if the identity associated with this principal is a member of the specified role, and false otherwise.

Programmatic Implementation

 public double GetMarketPrice(string symbol)

        {
            IPrincipal principal = Thread.CurrentPrincipal;
            if (!principal.IsInRole("MarketServiceSuperUser"))
                throw new AuthenticationException("Access Denied");

            GetServiceContext();
            //TODO: Fetch market price
            //sending hardcode value
            if (!symbol.EndsWith(".NSE"))
                throw new FaultException(
		new ValidationException { ValidationError = "Symbol is not valid" }, 
		new FaultReason("Validation Failed"));
           //send real price
            return 34.4d;
        }

image

Principal object contains caller’s identity and can be check if role is valid for this user. If Client user is not member of windows group then IsInRole will return false.

Declarative Implementation

Above behavior can also be implemented by PrincipalPermission attribute which take SecurityAction enum and role name.

      [PrincipalPermission(SecurityAction.Demand, Role = "MarketServiceSuperUser")]
       public double GetMarketPrice(string symbol)

        {
            //sending hardcode value
            if (!symbol.EndsWith(".NSE"))
                throw new FaultException(new 
		ValidationException { ValidationError = "Symbol is not valid" },
		new FaultReason("Validation Failed"));
           //send real price
            return 34.4d;
        }

Step 4: Run Client Application

  • Run with User which are not member of MarketServiceSuperUser.
   
static void Main(string[] args)
        {
       try
       {
       Console.WriteLine("Connecting to Service..");
        var proxy = new ServiceClient(new NetTcpBinding(), 
	new EndpointAddress("net.tcp://localhost:8000/MarketService"));
        proxy.ClientCredentials.Windows.ClientCredential.Domain = "domainuser";
        proxy.ClientCredentials.Windows.ClientCredential.UserName = "MarketServiceUser";
       proxy.ClientCredentials.Windows.ClientCredential.Password = "123456";
               
        Console.WriteLine("MSFT Price:{0}", proxy.GetMarketPrice("MSFT.NSE"));
        Console.WriteLine("Getting price for Google");
        double price = proxy.GetMarketPrice("GOOG.NASDAQ");
        }
           
       catch (FaultException ex)
        {
           Console.WriteLine("Service Error:" + ex.Detail.ValidationError);
        }
        catch (Exception ex)
         {
           Console.WriteLine("Service Error:" + ex.Message);
         }
        Console.ReadLine();
        }

In above code client will call with user which is member of MarketServiceSuperUser, service will authorize to access resources in service. 

  • Run with User which are not member of MarketServiceSuperUser.
proxy.ClientCredentials.Windows.ClientCredential.Domain = "domainuser"; 
proxy.ClientCredentials.Windows.ClientCredential.UserName = "MarketServiceInvalidUser";
proxy.ClientCredentials.Windows.ClientCredential.Password = "123456";

In this case SecurityAccessDeniedException  will generate with “Access Denied” message.

image

I hope this post brief you about implementation of role base security using windows group.

Implement windows authentication and security in WCF Service

This is continuation with previous post on “Security in WCF -I”.

Here I’ll explain how we can implement windows authentication with transport level security in intranet environment.

Windows authentication

In intranet environment, client and service are .Net application.Windows authentication is most suitable authentication type in intranet where client credentials stored in windows accounts & groups. Intranet environment address a wide range of business applications. Developers have more controlled in this environment.

For Intranet, you can use netTcpBinding,NetNamedPipeBinding and NetMsmqBinding for secure and fast communication.

Windows credential is default credential type and transport security is default security mode for these bindings.

Protection Level

You can set Transport Security protection level through WCF:

  • None: WCF doesn’t protect message transfer from client to service.
  • Signed: WCF ensures that message have come only from authenticated caller. WCF checks validity of message by checking Checksum at service side. It provides authenticity of message.
  • Encrypted & Signed: Message is signed as well as encrypted. It provides integrity, privacy and authenticity of message.

Configuration in WCF Service for Windows Authentication

    Service is hosted on netTcpBinding with credential type windows and protection level as EncryptedAndSigned.
var tcpbinding = new NetTcpBinding(SecurityMode.Transport);
//Client credential will be used of windows user
tcpbinding.Security.Transport.ClientCredentialType = 
		TcpClientCredentialType.Windows;
// When configured for EncryptAndSign protection level, WCF both signs the message and encrypts
//its content. The Encrypted and Signed protection level provides integrity,
//privacy, and authenticity.
tcpbinding.Security.Transport.ProtectionLevel = 
System.Net.Security.ProtectionLevel.EncryptAndSign;

Client credential type can be set by TcpClientCredentialType enum.

public enum TcpClientCredentialType
{
None,
Windows,
Certificate
}

Protection level can be set by ProtectionLevel  enum.

  // Summary:
    //     Indicates the security services requested for an authenticated stream.
    public enum ProtectionLevel
    {
        // Summary:
        //     Authentication only.
        None = 0,
        //
        // Summary:
        //     Sign data to help ensure the integrity of transmitted data.
        Sign = 1,
        //
        // Summary:
        //     Encrypt and sign data to help ensure the confidentiality and integrity of
        //     transmitted data.
        EncryptAndSign = 2,
    }

WCF Service Code

Service Host

class Program
    {
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://localhost:8045/MarketService");
using (var productHost = new ServiceHost(typeof(MarketDataProvider)))
  {
 var tcpbinding = new NetTcpBinding(SecurityMode.Transport);
 //Client credential will be used of windows user
 tcpbinding.Security.Transport.ClientCredentialType = 
			TcpClientCredentialType.Windows;
 // When configured for EncryptAndSign protection level, WCF both signs the message and encrypts
 //its content. The Encrypted and Signed protection level provides integrity,
 //privacy, and authenticity.
 tcpbinding.Security.Transport.ProtectionLevel = 
		System.Net.Security.ProtectionLevel.EncryptAndSign;

 ServiceEndpoint productEndpoint = productHost.
 AddServiceEndpoint(typeof(IMarketDataProvider), tcpbinding, 
		"net.tcp://localhost:8000/MarketService");

 ServiceEndpoint producthttpEndpoint = productHost.AddServiceEndpoint(
		typeof(IMarketDataProvider), new BasicHttpBinding(), 
		"http://localhost:8045/MarketService");

 productHost.Open();
 Console.WriteLine("The Market service is running and is listening on:");
 Console.WriteLine("{0} ({1})",
         productEndpoint.Address.ToString(),
         productEndpoint.Binding.Name);
 Console.WriteLine("{0} ({1})",
         producthttpEndpoint.Address.ToString(),
         producthttpEndpoint.Binding.Name);
 Console.WriteLine("\nPress any key to stop the service.");
 Console.ReadKey();
   }
        }


    }

Alternatively, you can configure the binding using a config file:

<bindings>

    <netTcpBinding>

    <binding name = "TCPWindowsSecurity">

     <security mode = "Transport">

          <transport

                 clientCredentialType = "Windows"

                 protectionLevel = "EncryptAndSign"

           />

     </security>

</binding>

</netTcpBinding>

</bindings>

Run WCF Service

image

Client Application

 static void Main(string[] args)
  {
  try
    {
     Console.WriteLine("Connecting to Service..");
     var proxy = new ServiceClient(new NetTcpBinding(), 
	new EndpointAddress("net.tcp://localhost:8000/MarketService"));
     Console.WriteLine("MSFT Price:{0}", proxy.GetMarketPrice("MSFT.NSE"));
     Console.WriteLine("Getting price for Google");
     double price = proxy.GetMarketPrice("GOOG.NASDAQ");
   }
  catch (FaultException ex)
  {
       Console.WriteLine("Service Error:" + ex.Detail.ValidationError);
  }
  catch (Exception ex)
  {
        Console.WriteLine("Service Error:" + ex.Message);
  }
  Console.ReadLine();
}

ServiceClient is custom class which inherits ClientBase<T> class in System.ServiceModel namespace to create channels and communication with service on endpoints.

public class ServiceClient : ClientBase, IMarketDataProvider
    {
     public ServiceClient()   { }
     public ServiceClient(string endpointConfigurationName) :
        base(endpointConfigurationName) { }
     
     public ServiceClient(string endpointConfigurationName, string remoteAddress) :
        base(endpointConfigurationName, remoteAddress)   { }
   
     public ServiceClient(string endpointConfigurationName, 
		System.ServiceModel.EndpointAddress remoteAddress) :
	        base(endpointConfigurationName, remoteAddress)
        { }
     public ServiceClient(System.ServiceModel.Channels.Binding binding, 
			System.ServiceModel.EndpointAddress remoteAddress) :
           base(binding, remoteAddress)
        {}
	/// 
        /// IMarketDataProvider method
        /// 
        /// 
        ///     
	public double GetMarketPrice(string symbol)
        {
            return base.Channel.GetMarketPrice(symbol);
        }
    }

Verify User credentials in Service

You can see caller information in WCF service by ServiceSecurityContext class.  Every operation on a secured WCF service has a security call context. The security call context is represented by the class ServiceSecurityContext.The main use for the security call context is for custom security mechanisms, as well as analysis and auditing.

ServiceSecurityContext.Current in Quickwatch window.

 

image

Send Alternate Windows credentials to Service

WCF also give option to send alternate windows credential from client. By default it send logged in user credential. You can send alternate credential like below

proxy.ClientCredentials.Windows.ClientCredential.Domain = "mydomain";
  
proxy.ClientCredentials.Windows.ClientCredential.UserName = "ABC";
proxy.ClientCredentials.Windows.ClientCredential.Password = "pwd";

Now If I run client application with changed credentials, if credentials are of valid windows user, service will authenticate caller else it will reject caller request. In my case I deliberately gives wrong credential to produce reject exception.

Service sends “System.Security.Authentication.InvalidCredentialException with message "The server has rejected the client credentials.”

image

I hope you understood windows authentication concept here. If you have any question please feel free to send me comments.

You can download code here:

https://skydrive.live.com/embed?cid=D5CF070E5761448A&resid=D5CF070E5761448A%21883&authkey=AKTA02kMiUv-6qc

Something about Security in WCF- I

Authentication and authorization are key aspects for secure communication between client and server. The service needs to authenticate its callers and correspondingly allow to use allowed operations. Service level authentication is not only thing for secure communication, messages should also be secure so that no tampering can happen. WCF supports variety of authentication mechanism:

None: Anonumous access to service. No authentication of caller.

Windows: Caller provides windows credentials (token or ticket) and service authenticate against windows users.

Username/Password:Caller sends user and password, this credentials validated against database or any credential store.

X509 certificate: Client and service has certification installed already. Service looks up for certificate from caller and authenticate it.

Custom mechanism: developer can develop and implement own authentication mechanism.

Tokens: client and service rely on third party authentication, in this case caller sends token that is authentication in service side.

Besides these authentication mechanism, communication should be secure at communication protocols and messages level as well. I’ll discuss Transfer Security modes here and how WCF support these modes:

Transfer Security Modes

  • None: No security at a all. Service will not get any client credentials. High risk for tampering of messages.
  • Transport Security: transport via secure communication protocols like Https,TCP,IPC and MSMQ. All communications on channels encrypted in these protocols. It is the simplest way of achieving transfer security, and the most performant option. Its main downside is that it can only guarantee transfer security point-to-point, meaning when the client connects directly to the service. Transport security is typically used only by intranet applications where you have more controlled environment.
  • Message Security: In this security, message gets encrypted. It provides privacy and mutual authentication. Encrypted messages can be transported via non secure protocols like http. Message security provides for end-to-end security, regardless of the number of intermediaries involved in transferring the message and regardless of whether or not the transport is secure. The downside of Message security is that it may introduce call latency due to its inherent overhead. Message security is typically used by Internet applications, where the call patterns are less chatty and the transport is not necessarily secure.
  • Mixed: Transport Security for message integrity and privacy, it uses message security for security client’s credentials. Very rarely used.
  • Both: Transport Security + Message Security to provide more security.

How Transfer Security mapped in WCF?

WCF Binding None Transport Security Message Security Mixed Both
basicHttpBinding yes(default) yes yes yes No
netTcpBinding (TCP) yes yes(default) yes yes No
netNamedPipeBinding (IPC) yes yes(default) No No No
WSHttpBinding yes yes yes(default) No No
NetMsmqBinding yes yes(default) yes No yes

Implementation in WCF

Transfer security controlled by enums in .net. Enum can be passed in constructor of bindings. Only valid Transfer Security will be available enums like netNamedPipeBinding only supports none and transport security so only “None” and “Transport” will be available as options.

BasicHttpSecurityMode:

public enum BasicHttpSecurityMode
{
None,
Transport,
Message,
TransportWithMessageCredential,
TransportCredentialOnly
}

Programmatically Implementation in code;

BasicHttpBinding binding1 = new BasicHttpBinding(BasicHttpSecurityMode.Message);
BasicHttpBinding binding2 = new BasicHttpBinding();
binding2.Security.Mode = BasicHttpSecurityMode.Message;

Configuration in Config File:

  • SecurityMode: it is  used in netTcpBinding and WSHttpBinding
public enum SecurityMode
{
None,
Transport,
Message,
TransportWithMessageCredential //Mixed
}

Programmatically Implementation in code

var productEndpoint = productHost.AddServiceEndpoint(typeof(IMarketDataProvider),
new NetTcpBinding(SecurityMode.Transport), "net.tcp://localhost:8000/MarketService");

NetNamedPipeSecurityMode: Use for IPC binding (netNamedPipeBinding)

public enum NetNamedPipeSecurityMode
{
None,
Transport
}

var bindingIPC = new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport);

NetMsmqSecurityMode: Use for MSMQ binding

public enum NetMsmqSecurityMode
{
None,
Transport,
Message,
Both
}
NetMsmqBinding Binding1 = new NetMsmqBinding(NetMsmqSecurityMode.Message);

 

I’ll cover implementation of different types of authentication in next blog: Something about Security in WCF- II

Get WCF Service Metadata on client application

Sometimes the client needs to programmatically verify whether a particular endpoint supports a particular contracts. Suppose Application administrator deployed application but it was pointing to development environment or some other address. If this feature implemented in application then he can get to know there is difference in service contracts or endpoints. He can then point to correct endpoints to run properly. This feature can reduce unnecessary diagnosis of errors on production system.

In order to support this feature client application should able to fetch metadata of service. This is not valid in case of netTcpBinding.

Metadata Processing

The metadata may be available either in special metadata exchange endpoints (if the service supports them), or over the HTTP-GET protocol. When you use HTTP-GET, the address of the metadata exchange is the HTTP-GET address suffixed by ?wsdl.

WCF Service

I hosted wcf service with HttpGetEnabled=”true” configuration. This is configuration on service side.

<?xml version="1.0"?>
<configuration>
 
  <system.web>
   </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8045/MarketService"
            httpGetBinding="webHttpBinding" httpGetBindingConfiguration="" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <services>
      <service name="MyService">
        <endpoint address="net.tcp://localhost:8000/MyService" binding="netTcpBinding"
          name="tcpendpoint" contract="IMarketDataProvider" />
        <endpoint address="http://localhost:8045/marketservice" binding="basicHttpBinding"
          bindingConfiguration="httpbinding" name="httpservicepint" contract="MarketApi.IMarketDataProvider" />
      </service>
    </services>
    <bindings>
      <basicHttpBinding>
        <binding name="httpbinding" />
      </basicHttpBinding>
      <netTcpBinding>
        <binding name="tcpbinding" transactionFlow="true" />
      </netTcpBinding>
    </bindings>
  </system.serviceModel>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>

</configuration>

This service is running on two bindings : tcpbinding and httpbinding with endpoints address net.tcp://localhost:8000/MyService" and http://localhost:8045/marketservice.

<serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8045/MarketService"
httpGetBinding="webHttpBinding" httpGetBindingConfiguration="" />

This configuration ensure that service metadata should be exposed and can be get via httpGetUrl. So wsdl will be available on http://localhost:8045/MarketService?wsdl address.

Service Host Code

 class Program
    {
        static void Main(string[] args)
        {
            Uri baseAddress = new Uri("http://localhost:8045/MarketService");
            using (var productHost = new ServiceHost(typeof(MarketDataProvider)))
            {
                ServiceEndpoint productEndpoint = productHost.AddServiceEndpoint(
			typeof(IMarketDataProvider), new NetTcpBinding(), 
			"net.tcp://localhost:8000/MarketService");
                ServiceEndpoint producthttpEndpoint = productHost.AddServiceEndpoint(
			typeof(IMarketDataProvider), new BasicHttpBinding(), 
			"http://localhost:8045/MarketService");

                productHost.Open();
                Console.WriteLine("The Market service is running and is listening on:");
                Console.WriteLine("{0} ({1})",
                  productEndpoint.Address.ToString(),
                  productEndpoint.Binding.Name);
                Console.WriteLine("{0} ({1})",
                  producthttpEndpoint.Address.ToString(),
                  producthttpEndpoint.Binding.Name);
                Console.WriteLine("\nPress any key to stop the service.");
                Console.ReadKey();
            }
        }


    }

 

Access Metadata on Client Side

MetadataExchangeClient class in System.ServiceModel.Description namespace uses for downloading service metadata on client.

Constructor on MetadataExchangeClient accepts endpoint address instance wrapping the metadata exchange address and enum which specify mode to use when downloading the metadata. It can be MetaDataExchange or HttpGet.

Here is code which extract metadata information:

	
	  static void GetMetadata()
        {
            Uri mexAddress = new Uri("http://localhost:8045/marketservice");
            var mexClient = new MetadataExchangeClient(mexAddress, 
		MetadataExchangeClientMode.HttpGet);
            MetadataSet metadata = mexClient.GetMetadata();
            MetadataImporter importer = new WsdlImporter(metadata);
            ServiceEndpointCollection endpoints = importer.ImportAllEndpoints();

            foreach (var end in endpoints)
                Console.WriteLine("Endpoints on server {0}", end.Address);
            
            ContractDescription description =
            ContractDescription.GetContract(typeof(IMarketDataProvider));
            bool contractSupported = endpoints.Any(endpoint =>
            endpoint.Contract.Namespace == description.Namespace &&
            endpoint.Contract.Name == description.Name);

            if (!contractSupported)
                throw new Exception("Not supported service contracts");

        }

Endpoints can also be accessed with MetadataResolver class.

 ServiceEndpointCollection endpoints =  	
	   MetadataResolver.Resolve(typeof(IMarketDataProvider),
            mexAddress, MetadataExchangeClientMode.HttpGet);

This way you can access service metadata on client side to verify about about endpoints, service contracts.

Resolve AddressAccessDeniedException: HTTP could not register URL http://+:80/ Error in WCF Service

I was facing one issue with hosting wcf service with httpbinding. I was getting below error message

"HTTP could not register URL http://+:8088/MarketService/. Your process does not have access rights to this namespace (see http://go.microsoft.com/fwlink/?LinkId=70353 for details)."

It clearly says service host process does not have access rights to run on particular port. To resolve I run command

on command prompt.Note command prompt should be "Run as administrator".

netsh http add urlact url="http://+:8088/MarketService user=domain\userid

After this my service was running perfect.

Source code in which I was getting problem

using (var productHost = new ServiceHost(typeof(MarketDataProvider))) 
     { 
        ServiceEndpoint productEndpoint = 
		productHost.AddServiceEndpoint(typeof(IMarketDataProvider), 
		new NetTcpBinding(), "net.tcp://localhost:8000/MarketService"); 
        ServiceEndpoint producthttpEndpoint = 
		productHost.AddServiceEndpoint(typeof(IMarketDataProvider), 
		new BasicHttpBinding(), "http://localhost:8088/MarketService"); 
                productHost.Open(); 
     } 

Have fun with coding!

I don’t want to be worry about WCF configuration on client side

I personally feels there is still too much configuration in setting up WCF service infact Microsoft has reduced in new .net frameworks.

If client application wants to consume WCF service then you need to create proxy class using Visual Studio and create configuration on Web/App config files (Visual Studio also generates many configuration). So if you are creating a WCF service and you want client should do minimum configuration setting, you can create proxy class your own which will encapsulate all configuration to connect WCF service and you can provide it sa DLL. It might not not relevant option for all scenarios because if your service would be consume by any clients type (.net,java,php etc.) then you might not need to provide it but this can be very useful if you know client applications are .Net client.

I am here taking an example of creating wcf service which is hosted on console application with tcp/ip bindings and consume by .net client application.

I structured server components in three projects

  • ServiceHostApp: Console self hosting application for WCF service
  • MarketDataProviderService: WCF project which has business logic and implements service contracts.
  • MarketApi: project which encapsulate DataContract, ServiceContract and channel creation code. This dll should deliver to client side so that all the service contract can accessed in client application.

Project: MarketApi

image

IMarketDataProvider.cs

It is service contract which has method GetMarketPrice.

 [ServiceContract]
    public interface IMarketDataProvider
    {
        [FaultContract(typeof(ValidationException))]
        [OperationContract]
        double GetMarketPrice(string symbol);

    }

ValidationException

It contains exception class which is using as fault contract in IMarketDataProvider.

  
    [DataContract]
    public class ValidationException
    {
        public ValidationException() { }
        [DataMember]
        public string ValidationError { get; set; }
    }

ServiceApi.cs

This class actually creating channels using factory class “ChannelFactory” provided by .net.

 
public class ServiceApi
    {
        public static T CreateServiceInstance(Binding binding,string endpoint)
        {
            var address = new EndpointAddress(endpoint);
            var factory = new ChannelFactory(binding,endpoint);
            return factory.CreateChannel();
        }

    }

CreateServiceInstance method is generic method which creates channels for any binding provided and endpoints.

Project: MarketDataProviderService

This project has implementation of service contract IMarketDataProvider.

 
public class MarketDataProvider : IMarketDataProvider
    {
        
       public double GetMarketPrice(string symbol)
        {
            //TODO: Fetch market price
            //sending hardcode value
            if (!symbol.EndsWith(".NSE"))
                throw new FaultException(
			new ValidationException { 
				ValidationError = "Symbol is not valid" 
				}, 
				new FaultReason("Validation Failed"));
           //send real price
            return 34.4d;
        }
    }

Project: Hosting Service

ServiceHostApp is console application which is hosting MarketDataProviderService.

 
 class Program
    {
        static void Main(string[] args)
        {
            using (var productHost = new ServiceHost(typeof(MarketDataProvider)))
            {
                ServiceEndpoint productEndpoint = productHost.AddServiceEndpoint(
			typeof(IMarketDataProvider), new NetTcpBinding(), 
			"net.tcp://localhost:8000/MarketService");
                productHost.Open();
                Console.WriteLine("The Market service is running and is listening on:");
                Console.WriteLine("{0} ({1})",
                  productEndpoint.Address.ToString(),
                  productEndpoint.Binding.Name);
                Console.WriteLine("\nPress any key to stop the service.");
                Console.ReadKey();
            }
        }
    }

ServiceHost class of System.ServiceModel namespace uses to host wcf service. You can add ServiceEndPoint to this class. Here I am running wcf service on tcp port 8000.

image

Now Let’s Create Client Application

Client application will not use proxy class generated by Visual studio, instead client application will use MarketApi.dll to communicate with Service.

  
 class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Connecting to Service..");
                var proxy = ServiceApi.CreateServiceInstance(
			new NetTcpBinding(), 
			"net.tcp://localhost:8000/MarketService");
                Console.WriteLine("MSFT Price:{0}",
			proxy.GetMarketPrice("MSFT.NSE"));
            }
            catch (FaultException ex)
            {
                Console.WriteLine("Service Error:" + ex.Detail.ValidationError);
            }
            Console.ReadLine();
        }

    }

Here CreateServiceInstance method create instance of IMarketDataProvider through NetTcpBinding on 8000 port.

proxy.GetMarketPrice method will call method on service. FaultException of validationException type is catched in catch block.

 

image

Raise FaultException

Now I want to test for if service sends fault exception if something goes wrong. In client application I am sending symbol which is not part of NSE exchange.

I am sending symbol as GOOG.NASDAQ to get market price. Service application will raise exception “Not valid symbol”.

 
 class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Connecting to Service..");
                var proxy = ServiceApi.CreateServiceInstance(
			new NetTcpBinding(), 
			"net.tcp://localhost:8000/MarketService");
                Console.WriteLine("MSFT Price:{0}",
			proxy.GetMarketPrice("MSFT.NSE"));
                Console.WriteLine("Getting price for Google");
                double price = proxy.GetMarketPrice("GOOG.NASDAQ");

                
            }
            catch (FaultException ex)
            {
                Console.WriteLine("Service Error:" + ex.Detail.ValidationError);
            }
            Console.ReadLine();
        }
    }

image

I have not used any other configuration like authentication, authorization etc. I just want to describe how we can create Api without configuration mess.

You can find source code of this example here.

https://skydrive.live.com/embed?cid=D5CF070E5761448A&resid=D5CF070E5761448A%21697&authkey=ANa5UmGIArTJJrs