Multiple Hosts?

I'm trying to configure multiple service hosts with multiple end points in each using self hosting.

The code looks something like this:

Uri baseAddress = new Uri("http://localhost:8080/OxfordCRMWCF");

ServiceHost sh1 = new ServiceHost(service1, baseAddress);

// --- Add a Service End Point ------------------------------------------
sh1.AddServiceEndpoint(contract1, new WSHttpBinding(), baseAddress.ToString());

// --- Activate the First Service -----------------------------------------
sh1.Open();

ServiceHost sh2 = new ServiceHost(service2, baseAddress);

// --- Add a Service End Point ------------------------------------------
sh2.AddServiceEndpoint(contract2, new WSHttpBinding(), baseAddress.ToString());

// --- Activate the Second Service --------------------------------------
sh2.Open();

When I attempt to open sh2, I get an error that says:

Duplicate registration for URI 'http://localhost:8080/OxfordCRMWCF': 'System.ServiceModel.Channels.HttpReplyChannelListener'.

Can someone please tell me what I'm doing wrong

Thanks,

Chuck




Answer this question

Multiple Hosts?

  • DragonsBlade

    You can add multiple endpoints to one servicehost, or, as you're trying to do, you can make multiple servicehosts each of which can support one or more endpoints.

    These servicehosts cannot share the same baseaddress. Just looking at your code though you may want to have one servicehost with multiple endpoints. IE:

    WSHttpBinding binding1 = new WSHttpBinding();
    Uri baseAddress1 = new Uri("http://localhost:23000/");
    ServiceHost host = new ServiceHost(typeof(Test), baseAddress1);

    EndpointAddress epa1 = new EndpointAddress(baseAddress1 + "MyTest/");
    EndpointAddress epa2= new EndpointAddress(baseAddress1 + "AnotherTest/");


    ServiceEndpoint sep1 = new ServiceEndpoint(ContractDescription.GetContract(typeof(IMessageContractTest)), binding1,epa1);
    ServiceEndpoint sep2 = new ServiceEndpoint(ContractDescription.GetContract(typeof(IXmlSerializerTest)), binding1, epa2);

    host.Description.Endpoints.Add(sep1);
    host.Description.Endpoints.Add(sep2);

    host.Open();

    Thanks!

    Scott



  • parag medsinge

    Hey Chuck,

    This is exactly what I was looking for. Thanks so much for the complete posting.


  • elle1

    I think multiple services with unique base addresses is what you want. You can play some tricks to get the URI's you want...

    For example, if you want two services each living at unique URI's:
    http://localhost/app/contract1
    http://localhost1/app/contract2

    You can use the full URI as the base address for each and just use an address of "" for the endpoints.


  • Visagar

    That looks like a very good solution, but I have a question...

    My services are currently organized into separate classes...for example

    [ServiceContract()]
    public interface IClientManagerServices
    {
    [OperationContract]
    ClientService1;

    [OperationContract]
    ClientService2;

    }

    [ServiceContract()]
    public interface IConsultantServices
    {
    [OperationContract]
    ConsultantService1;

    [OperationContract]
    ConsultantService2;

    }

    and each interface is associated with a separate class that implements those interfaces. (ClientManager Services and ConsultantSerrices) So it doesn't look like I can create a single service host to handle both. If I try to implement your approach with the classes as they exist like this:

    ServiceHost host = new ServiceHost(typeof(ClientServices), baseAddress1);

    I get an error that says:

    ServiceHost implementation type OxfordCRM.WCFServices.ClientManagerServices does not implement ServiceContract OxfordCRM.WCFServices.IConsultantServices

    Do I need to combine these classes somehow to make it work or is there a way I can get one service host to support multiple classes Perhaps I have to make a superordinate class that includes all the lower classes What's the best way to do that

    Thanks for your help,

    Chuck



  • Velan

    I would prefer to keep the classes separate if possible because there's quite a few of them and it would be very messy to combine them into one class. The initial prototype of this was done using webservices and we're trying to convert it to WCF and I'd like to keep it similar to the way the original webservices approach was done with separate classes.

    Is there a way to avoid having to combine these into a single class

    Thanks,

    Chuck



  • Rahul Singla

    Here's the code I came up with. I have quite a few of these services to implement so I created a function to create each one...that makes it easier to implement. Here's the code (only 2 example services are shown - the actual full implementation has about 20-30. Any comments or suggestions would be welcome.

    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace OxfordCRM.WCFConsoleApp
    {
    class Program
    {
    static void Main(string[] args)
    // **************************************************************************
    // Main Program to Start and Stop WCF Services
    // **************************************************************************
    {
    try
    {
    // --- Start the WCF Services -------------------------------------------
    ServiceManager.StartServices();

    // --- Display Confirmation Message to User -----------------------------
    Console.WriteLine("The Oxford CRM WCF Services Are Running.");

    // --- Wait for User Input ----------------------------------------------
    Console.ReadKey();

    // --- Stop the WCF Services --------------------------------------------
    ServiceManager.StopServices();
    }
    catch
    {
    throw;
    }
    }
    }
    }

    using OxfordCRM.WCFServices;
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.ServiceModel.Description;
    using System.Text.RegularExpressions;

    namespace OxfordCRM.WCFConsoleApp
    {
    internal class ServiceManager
    {
    // **************************************************************************
    // Holds a Reference to the Service Host Objects
    // **************************************************************************
    private static List<ServiceHost> serviceHosts = new List<ServiceHost>();

    // **************************************************************************
    // Holds a Reference to the Base Address of All Services
    // **************************************************************************
    private static Uri baseAddress;

    internal static void StartServices()
    // **************************************************************************
    // Starts the WCF Services
    // **************************************************************************
    {
    try
    {
    // --- Set the Base Address for the Services ------------------------
    baseAddress = new Uri("
    http://localhost:8080/OxfordCRMWCF");

    // --- Add Services with End Points and Startup Each ----------------
    AddService(typeof(ClientCompanies), typeof(IClientCompanies));
    AddService(typeof(Consultants), typeof(IConsultants));

    }
    catch
    {
    throw;
    }
    }

    internal static void StopServices()
    // **************************************************************************
    // Stops the WCF Services
    // **************************************************************************
    {
    try
    {
    // --- Shut Down All Open WCF Services ------------------------------
    foreach (ServiceHost sh in serviceHosts)
    {
    if (sh.State != CommunicationState.Closed) sh.Close();
    }
    }
    catch
    {
    throw;
    }
    }

    private static void AddService(Type serviceType, Type contractType)
    // **************************************************************************
    // Adds a Service End Point to the Service Host
    // **************************************************************************
    {
    try
    {
    // --- Create a New Base Address for the Service --------------------
    string serviceTypeName = GetServiceName(serviceType.ToString());
    string serviceAddress = baseAddress.ToString() + "/" +
    serviceTypeName;
    Uri newBaseAddress = new Uri(serviceAddress);

    // --- Create a New Service Host ------------------------------------
    WSHttpBinding binding = new WSHttpBinding();
    ServiceHost sh = new ServiceHost(serviceType, newBaseAddress);

    // --- Create a New Service End Point and Add to Host ---------------
    EndpointAddress epa = new EndpointAddress(newBaseAddress);
    ServiceEndpoint sep = new ServiceEndpoint(
    ContractDescription.GetContract(contractType), binding, epa);
    sh.Description.Endpoints.Add(sep);

    // --- Save a Reference to the Service Host for Shutdown ------------
    serviceHosts.Add(sh);

    // --- Activate the Service Host ------------------------------------
    sh.Open();
    }
    catch
    {
    throw;
    }
    }


    // Method GetServiceName
    private static string GetServiceName(string serviceType)
    {
    // **************************************************************************
    // Gets the ServiceName from a Service Type
    // **************************************************************************
    try
    {
    // --- Throw an Error if Null -------------------------------------------
    if (string.IsNullOrEmpty(serviceType))
    {
    throw new ArgumentNullException("serviceType");
    }

    // --- Extract the Last Word at End of Service Type ---------------------
    Regex r = new Regex("(\\.)");
    string[] strArray = r.Split(serviceType);
    return strArray[strArray.Length - 1];
    }
    catch
    {
    throw;
    }
    }
    }
    }



  • SivaS

    One possible solution is to have your class implement the interfaces for both contracts. So for example:

    class ClientServices : IConsultantServices, IClientManagerServices

    {

    .........

    }

    That way you can have your servicehost implement both endpoints. You would have to move the implementations to that one class. Will that work for you

    Thanks!

    Scott



  • Multiple Hosts?