Multiple WCF services in one solution with multiple endpoints and hosting

You might have tried one WCF service to learn about WCF or some small application. In real application with only one WCF service, it is difficult to handle applications in all aspects.

So in this article, I will explain to you how to create multiple WCF services to serve different entities in one solution with different endpoints and bindings. And also tells you how to host these services in IIS 7+ or in Windows Services.

For this tutorial, we will create two WCF services as 1.CustomerService and 2.OrderService

  1. Start with WCF Service Library

    If you would like to know about how to start with WCF go through the article Create a new WCF service library and test using WCFTestClient

  2. Northwind Solution

    Create an empty solution by opening Visual Studio and click on File menu -> Project -> Click on Other Project Types from Installed Template -> Select Blank Solution

    Give a name as Northwind.

  3. NorthwindServices Service library

    Add NorthwindServices WCF Service Library to Northwind solution by right click on solution -> Add -> New Project -> Choose Visual C# from Installed templates -> Select WCF -> Select WCF Service Library

    Delete default IService1.cs, Service1.cs files from library.

  4. Service Contracts

    1. Add ServiceContracts Folder to Northwind Service Library project.
    2. Add the ICustomerService contract to the ServiceContracts folder created in the previous step.

      Right click on ServiceContracts and add new Interface to folder. Name it as ICustomerService. Add ServiceContract attribute to ICustomer.

    3. Add OperationContract to ICustomerService which will be accessible to the clients. Your ICustomerService should look like.

                          
      using System.ServiceModel;
      
      namespace NorthwindServices.ServiceContracts
      {
          [ServiceContract(Namespace = "https://geeksarray.com/services/customer")]
          public interface ICustomerService
          {
              [OperationContract]
              string GetCustomerName(int CustomerID);
      
              [OperationContract]
              string GetCustomerCity(int CustomerID);
      
              [OperationContract]
              int GetCustomerCount();
          }
      }
                          
    4. Add IOrderService contract to ServiceContracts folder and its OperationContract as we added for ICustomerService.

      IOrderService should look like

                          
      using System.ServiceModel;
      
      namespace NorthwindServices.ServiceContracts
      {
          [ServiceContract(Namespace = "https://geeksarray.com/services/order")]
          public interface IOrderService
          {
              [OperationContract] 
              string GetOrderDate(int orderID);
              
              [OperationContract] 
              string GetOrderAmount(int OrderID);
      
              [OperationContract] 
              string GetShipCountry(int orderID);
          }
      }
                          
  5. Datastore

    Add two new XML files name it as Customers.xml and Orders.xml. These xml files will be used as datastore for OrderService and CustomerService respectively.

    Customers.xml

                
    <?xml version="1.0" standalone="yes"?>
    <DocumentElement>
        <Customer>
            <CustomerID>1</CustomerID>
            <CompanyName>Let's Stop N Shop</CompanyName>
            <City>Mumbai</City>
        </Customer>
        <Customer>
            <CustomerID>2</CustomerID>
            <CompanyName>Hungry Coyote Import Store</CompanyName>
            <City>Mumbai</City>
        </Customer>      
        <Customer>
            <CustomerID>4</CustomerID>
            <CompanyName>Andy's Seasoning</CompanyName>
            <City>Delhi</City>
        </Customer>
    </DocumentElement>
                        
                

    Orders.xml

                
    <?xml version="1.0" standalone="yes"?>
    <DocumentElement>
        <Orders>
            <OrderID>10248</OrderID>
            <OrderDate>1996-07-04</OrderDate>
            <ShippedDate>1996-07-16</ShippedDate>
            <ShipCountry>France</ShipCountry>
            <OrderTotal>650</OrderTotal>
        </Orders>      
        <Orders>
            <OrderID>10250</OrderID>
            <OrderDate>1996-07-08</OrderDate>
            <ShippedDate>1996-07-12</ShippedDate>
            <ShipCountry>Brazil</ShipCountry>
            <OrderTotal>2170</OrderTotal>
        </Orders>
        <Orders>
            <OrderID>10251</OrderID>
            <OrderDate>1996-07-08</OrderDate>
            <ShippedDate>1996-07-15</ShippedDate>
            <ShipCountry>France</ShipCountry>
            <OrderTotal>1057</OrderTotal>
        </Orders>
    </DocumentElement>
                        
                
  6. Implementation of Customer and Order WCF service

    1. Add a Services folder to the root of the NorthwindServices service library.
    2. Add a new class to the Services folder created in the previous step. Name the class as CustomerService and implement the ICustomerService service contract.
                          
      using NorthwindServices.ServiceContracts;
      using System.Xml.Linq; 
      
      namespace NorthwindServices.Services
      {
          [ServiceBehavior(Namespace="https://geeksarray.com/services/customer")]  
          public class CustomerService : ICustomerService 
          {
              public string GetCustomerName(int CustomerID)
              {
                  XDocument doc = XDocument.Load("C:\\Customers.xml");
      
                  string companyName =
                      (from result in doc.Descendants("DocumentElement")
                      .Descendants("Customer")
                          where result.Element("CustomerID").Value 
                              == CustomerID.ToString()
                          select result.Element("CompanyName").Value)
                      .FirstOrDefault<string>();
      
                  return companyName;
              }
      
              public string GetCustomerCity(int CustomerID)
              {
                  XDocument doc = XDocument.Load("C:\\Customers.xml");
      
                  string companyName =
                      (from result in doc.Descendants("DocumentElement")
                      .Descendants("Customer")
                          where result.Element("CustomerID").Value 
                              == CustomerID.ToString()
                          select result.Element("City").Value)
                      .FirstOrDefault<string>();
      
                  return companyName;
              }
      
              public int GetCustomerCount()
              {
                  XDocument doc = XDocument.Load("C:\\Customers.xml");
      
                  return doc.Descendants("Customer").Count();  
              }
          }
      }
                      
    3. Add a new class to Services folder. Name the class as OrderService and implement the IOrderService service contract.

                          
      using NorthwindServices.ServiceContracts;
      using System.Xml.Linq;
      
      namespace NorthwindServices.Services
      {
          [ServiceBehavior(Namespace="https://geeksarray.com/services/order")]  
          public class OrderService : IOrderService
          {
              public string GetOrderDate(int orderID)
              {
                  XDocument doc = XDocument.Load("C:\\Orders.xml");
      
                  string orderDate =
                      (from result in doc.Descendants("DocumentElement")
                      .Descendants("Orders")
                          where result.Element("OrderID").Value 
                              == orderID.ToString()
                          select result.Element("OrderDate").Value)
                      .FirstOrDefault<string>();
      
                  return orderDate;
              }
      
              public string GetOrderAmount(int orderID)
              {
                  XDocument doc = XDocument.Load("C:\\Orders.xml");
      
                  string orderTotal =
                      (from result in doc.Descendants("DocumentElement")
                      .Descendants("Orders")
                          where result.Element("OrderID").Value 
                              == orderID.ToString()
                          select result.Element("OrderTotal").Value)
                      .FirstOrDefault<string>();
      
                  return orderTotal;
              }
      
              public string GetShipCountry(int orderID)
              {
                  XDocument doc = XDocument.Load("C:\\Orders.xml");
      
                  string shipCountry =
                      (from result in doc.Descendants("DocumentElement")
                      .Descendants("Orders")
                          where result.Element("OrderID").Value 
                                  == orderID.ToString()
                          select result.Element("ShipCountry").Value)
                      .FirstOrDefault<string>();
      
                  return shipCountry;
              }
          }
      }                   
                     

      Sometimes in service implementation exception occurs. Service exception needs to be handle by using FaultContract .

  7. Service Endpoint

    Add Service Endpoints for CustomerService and OrderService.

    In real time applications wsHttpBinding is used for HTTP communication like with web applications and netNamedPipeBinding . is used for the applications which are running on same machine for example to execute some jobs, update inventory by back office application.

    netNamedPipeBinding gives you the best possible performance if the client is on the same machine.

    So for CustomerService and OrderService we will use both bindings.

    Add below service model configuration to your service library configuration.

                
    <system.serviceModel>
    <services>
    <service name="NorthwindServices.Services.CustomerService" 
                        behaviorConfiguration ="ServiceBehavior">
    <host>
        <baseAddresses>
        <add baseAddress="http://localhost:7741/NorthwindServices/Services
                                /CustomerService" /> 
        <add baseAddress="net.pipe://localhost/Services/CustomerService" />
        </baseAddresses>
    </host>
    
    <endpoint address ="" binding="wsHttpBinding"
            contract="NorthwindServices.ServiceContracts.ICustomerService"
            bindingNamespace = "https://geeksarray.com/services/customer" />
    <endpoint address="mex" binding="mexHttpBinding" 
                    contract="IMetadataExchange"/>
    
    <endpoint address ="" binding ="netNamedPipeBinding" 
            contract ="NorthwindServices.ServiceContracts.ICustomerService"
            bindingNamespace = "https://geeksarray.com/services/customer"  />
    <endpoint address="mex" binding="mexNamedPipeBinding" 
                    contract="IMetadataExchange"/>
    </service>
    
    <service name="NorthwindServices.Services.OrderService" 
                            behaviorConfiguration ="ServiceBehavior">
    <host>
        <baseAddresses>
        <add baseAddress="http://localhost:7741/NorthwindServices/Services
                                    /OrderService" />
        <add baseAddress="net.pipe://localhost/Services/OrderService" />
        </baseAddresses>
    </host>
    
    <endpoint address ="" binding="wsHttpBinding"
            contract="NorthwindServices.ServiceContracts.IOrderService"
            bindingNamespace = "https://geeksarray.com/services/order" />
            
    <endpoint address="mex" binding="mexHttpBinding" 
                    contract="IMetadataExchange"/>
    
    <endpoint address = "" binding ="netNamedPipeBinding"
            contract = "NorthwindServices.ServiceContracts.IOrderService"
            bindingNamespace = "https://geeksarray.com/services/order"  />
    <endpoint address="mex" binding="mexNamedPipeBinding" 
                    contract="IMetadataExchange"/>
            
    </service>
    </services>    
    <behaviors>
        <serviceBehaviors>
        <behavior name ="ServiceBehavior" >
            <serviceMetadata httpGetEnabled="True"/>
            <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
        </serviceBehaviors>
    </behaviors>
    </system.serviceModel>    
                        
                
  8. Hosting Services to IIS and Windows Services

    We will be hosting Customer service and Order Service to IIS and Windows Services.

    1. Hosting WCF Services in IIS 7.0+ Go through the article for hosting services in IIS WCF service in IIS this gives you steps to host the ProductService WCF Servie in IIS. You need to follow same steps for Customer Service and Order Service.

      Create a folder Hosts in your service library application and place the CustomerServiceHost.svc and OrderServiceHost.svc before hosting the service in IIS.

      While hosting WCF service with netNamedPipeBinding in IIS some bindings errors might occur. This article hosting WCF service with netNamedPipeBinding in IIS might help you to resolve those errors.

    2. Hosting WCF Services in Windows Services Host WCF CustomerService and OrderService in Windows service.

      Make sure <System.ServiceModel> of app.config file of Windows Services and WCF Service Library are identical.

  9. CustomerService and OrderService Clients

    Add client application as suggested in the previous step. Ideally, we should have add two applications to use those services.

    Console application to use netNamedPipeBindings and web application to test wsHttpBinding (you can test both bindings from any application as long as service and client are on the same machine.)

    1. Console Application Add reference a to CustomerService and OrderService. Use the below addresses to add service reference.
                          
              net.pipe://localhost/Services/CustomerService 
      
              net.pipe://localhost/Services/OrderService
                                  
                      

      When you add service you will have client endpoint in your console applications app.config. You will have both netNamedPipeBinding and wsHttpBinding endpoint in your client app.config.

      Add below code to the client application

                          
      using NorthwindBackOffice.CustomerServiceRef;
      using NorthwindBackOffice.OrderServiceRef;
      
      namespace NorthwindBackOffice
      {
      class Program
      {
      static void Main(string[] args)
      {
          ShowCustomerDetails();
          Console.WriteLine(); 
          ShowOrderDetails();
          Console.Read(); 
      }
      
      private static void ShowCustomerDetails()
      {
          string customerCity = string.Empty;
          string customerName = string.Empty;
          int customerCount = 0;
      
          using (CustomerServiceClient client =
          new CustomerServiceClient("NetNamedPipeBinding_ICustomerService"))
          {
                  customerCity = client.GetCustomerCity(2);
                  customerName = client.GetCustomerName(2);
                  customerCount = client.GetCustomerCount();   
          }
      
          Console.WriteLine("******* Customer Data **************");
          Console.WriteLine("Customer Name : " + customerName);   
          Console.WriteLine("Customer City : " + customerCity);
          Console.WriteLine("Total customer count : "
                                  + customerCount.ToString());    
      }
      
      private static void ShowOrderDetails()
      {
          string orderAmount = string.Empty;
          string orderDate = string.Empty;
          string orderShip = string.Empty;
      
          using (OrderServiceClient client = 
          new OrderServiceClient("NetNamedPipeBinding_IOrderService"))
          {
              orderAmount = client.GetOrderAmount(10250);
              orderDate = client.GetOrderDate(10250);
              orderShip = client.GetShipCountry(10250);
          }
      
          Console.WriteLine("******* Order Data **************");
          Console.WriteLine("Order Amount : " + orderAmount);
          Console.WriteLine("Order Date : " + orderDate);
          Console.WriteLine("Ship Country : " + orderShip);
      }
      }
      }
                      

      Notice that we have mentioned a binding name while creating the instance of service because two endpoints are available for one service with different bindings.

    2. WebApplication as a client for WCF services Add a web application to the solution and add service reference using the below address.

          http://localhost:7741/NorthwindServices/Services/CustomerService
      
          http://localhost:7741/NorthwindServices/Services/OrderService
                      

Source code on Git hub Source Code on Github

Speak your mind
Please login to post your comment!


Blog Search





If you like my content please feel free to buy me coffee. Buy Me A Coffee