Hosting Multiple Endpoints in a single Windows Service

Jun 26, 2009 at 5:04 PM
Hi,

I've used WSSF to build an application that implements multiple service
contracts. Hosting this in the ASP.NET Development Web Server is no
problem. I just have one web.config and many <client> sections, each
defining its own endpoint.

I now need to host these services in a Windows Service, but I can't find
a way to do this in a single Windows Service Host.

When I move to a Windows Service host, using TCP, its app.config file
looks something like this (reflecting the structure of the relevant part
of the web.config file for the ASP.NET Development Server host):

<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
...
</netTcpBinding>
</bindings>
<client>
<endpoint address =
"net.tcp://localhost:8371/Uwic.AnnualLeave.ServiceImplementation.UnitService"

binding="..."
contract="..."
bindingConfiguration="AnEndpont"
name="AnEndpoint" />
</client>
<client>
<endpoint address =
"net.tcp://localhost:8371/Uwic.AnnualLeave.ServiceImplementation.RoleService"

binding="..."
contract="..."
bindingConfiguration="AnotherEndpont"
name="AnotherEndpoint" />
</client>
<client>
<!-- details as above for another client sections -->
</client>

etc - for more client sections

</system.serviceModel>
</configuration>

The trouble is that it appears that I need a separate Windows Service
for each service reference, because when I tell the Windows Service, in
its OnStart() method, what type of object it is hosting, I don't see a
way of telling it that it is hosting seven different objects, each
referred to separately in the app.config file.

Is that right, or am I missing something?

Needing to create many services in this way would be a real problem for us.

Thanks in advance


Peter
Jun 26, 2009 at 8:55 PM

Hi Peter,

You may find some self hosting scenarios out there. Here is an example where you can get an idea in particular in sections "Hosting the Service" and "Adding Endpoints" sample code.

http://csharp-codesamples.com/2009/02/data-transfer-using-self-hosted-wcf-service/

 

Jun 26, 2009 at 11:08 PM
hernandelahitte wrote:
>
> From: hernandelahitte
>
> Hi Peter,
>
> You may find some self hosting scenarios out there. Here is an example
> where you can get an idea in particular in sections "Hosting the
> Service" and "Adding Endpoints" sample code.
>
> http://csharp-codesamples.com/2009/02/data-transfer-using-self-hosted-wcf-service/
>

Not really. The code you point to has the same problem. It can only
host one type (DataUploader in the code you point to):


ServiceHost host = new ServiceHost(typeof(DataUploader));


I don't understand why the ASP.NET Development Server can host many
types, but this facility doesn't appear to be available for self-hosting
solutions. It's not a problem with plain old remoting either. I can
add as many types as I like to my config files and they all get hosted
by the same Windows service.

As I said in my original post, if this can't be done, it looks as though
WCF (never mind WSSF) is a non-starter for us. Or am I missing
something incredibly obvious? For example, I've (just) found code like
this in an example Windows service:

// The main entry point for the process
static void Main()
{
System.ServiceProcess.ServiceBase[] ServicesToRun;

// More than one user Service may run within the same process.
To add
// another service to this process, change the following line to
// create a second service object. For example,
//
// ServicesToRun = new System.ServiceProcess.ServiceBase[]
{new Service1(), new MySecondUserService()};
//
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new
OPCWebClient_CRead() };

System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}

Is this what I have to do to host many services in the same Windows
Service host under WCF? It's very late here now and I'm very tired: so
I'll have to give it a rest for a while. I'll try to experiment with
that tomorrow. I have to say I don't really see how I could use that,
at the moment.


Thanks for taking the time to answer, and if you could shed any further
light on things, I'd be very grateful.

Cheers



Peter
Jun 27, 2009 at 1:45 AM

Hi Peter,

I think that you can actually host many services simply by creating separeate instances of ServiceHost like shown here:

http://stackoverflow.com/questions/54419/how-to-host-2-wcf-services-in-1-windows-service

Notice the first answer where it shows how to start each instance:

 // Start the Windows service.
   
protected override void OnStart( string[] args )
   
{
       
// Call all the set up WCF services...
        MyWCFService1
.StartService();
       
//MyWCFService2.StartService();
       
//MyWCFService3.StartService();
   
}

Jun 27, 2009 at 11:26 AM
hernandelahitte wrote:
>
> From: hernandelahitte
>
> Hi Peter,
>
> I think that you can actually host many services simply by creating
> separeate instances of ServiceHost like shown here:
>
> http://stackoverflow.com/questions/54419/how-to-host-2-wcf-services-in-1-windows-service
>
> Notice the first answer where it shows how to start each instance:
>
> // Start the Windows service.
> protected override void OnStart( string[] args )
> {
> // Call all the set up WCF services...
> MyWCFService1.StartService();
> //MyWCFService2.StartService();
> //MyWCFService3.StartService();
> }
>

Thanks for that.

I'm going to try it later and will let you know how I get on, because
it's actually quite an important matter (IMHO) as it seems to me that
WSSF implies using many services in the design of the server-side
elements of an application of any size. For instance, in a simple case
you might have - say - half a dozen or so entities that you want to
deal with: in the most obvious example, these might represent tables or
views in your back end database. You might have something like five or
six operations on each of these entities, meaning that you have a total
of around 30 or so operations with associated data, fault and message
contracts.

Expressing all these as a single contract does not seem very clean to
me. It also makes the application less modular and less re-usable.

So hosting multiple services in one host looks like a big deal. And
Windows Service hosting is very common. We have a policy, for example,
banning Web servers from our application servers, for security reasons.

Thanks for your interest. I'm sure what you say is right, so I'll get
onto it later in the day.

Cheers


Peter
Jun 28, 2009 at 2:30 PM
hernandelahitte wrote:
>
> From: hernandelahitte
>
> Hi Peter,
>
> I think that you can actually host many services simply by creating
> separeate instances of ServiceHost like shown here:
>
> http://stackoverflow.com/questions/54419/how-to-host-2-wcf-services-in-1-windows-service
>
> Notice the first answer where it shows how to start each instance:
>
> // Start the Windows service.
> protected override void OnStart( string[] args )
> {
> // Call all the set up WCF services...
> MyWCFService1.StartService();
> //MyWCFService2.StartService();
> //MyWCFService3.StartService();
> }
>

Yep. That appears to be it. I've got it working for the first two of
my seven services. I assume that if it works for two, then it'll work
for any number.

The full story (for posterity) is:

Add references in your Windows Service Host project, to
System.ServiceModel and to your service implementation. The latter is
needed for the types that the Windows Service Host is going to host.

Add using statements to save yourself a bit of typing.

In your class that inherits from ServiceBase, declare an instance
variable of type ServiceHost for each service that you want to host
(i.e. for each type in your service implementation). So, in my case
I've got something like:

public partial class AnnualLeaveServiceWindowsHost : ServiceBase
{
ServiceHost roleHost = null;
ServiceHost unitHost = null;

...

}


In the OnStart() method, instantiate each ServiceHost, and open it:

protected override void OnStart(string[] args)
{
if (roleHost != null)
roleHost.Close();

roleHost = new ServiceHost(typeof(RoleService));
roleHost.Open();

if (unitHost != null)
unitHost.Close();

unitHost = new ServiceHost(typeof(UnitService));
unitHost.Open();
}

Close each running service in the OnStop() method:

protected override void OnStop()
{
if (roleHost != null)
{
roleHost.Close();
roleHost = null;
}

if (unitHost != null)
{
unitHost.Close();
unitHost.Close();
}
}

I hope this might be of use to someone else.

Cheers, and thanks for the help.



Peter