0

For quite a while we have had a service hosted in IIS, and another library/application has been using the same service as a self hosted service.

The IIS service is hosted using http/https bindings and the self hosted service is hosted using a net named pipe binding.

Now somewhere in the IIS hosted application we started using the component that is self hosted (from another service). Due to the fact that the web.config is configured with http bindings but the self hosted one sends in a net.pipe:// url I get an error when trying to create a ServiceHost instance.

The error i get:

Could not find a base address that matches scheme http for the endpoint with binding WSHttpBinding. Registered base address schemes are [net.pipe].

The code that is responsible for that error:

var host = new ServiceHost(typeof(Service1), new Uri("net.pipe://localhost/" + guid.ToString()));

My Web.config has the following section:

<service name="WcfServiceLibrary1.Service1">
    <endpoint address="" binding="wsHttpBinding" name="endpoint1" contract="WcfServiceLibrary1.IService1" />
 </service>

And if i remove that the self-hosting works fine but the IIS hosting does not work.

Now I am aware that I have at least two options.

  1. Add multiple Uri to the ServiceHost() constructor call
  2. Implement the static Configure method on the service that has the self-hosting and call enableProtocol on required bindings (as described on msdn)

However I was wondering if there was some general way that I can get the desired result of having both hosting types in the same process without having to resort to one of the two above options.

For instance, is it possible to define protocols on a "global" level either via configuration or via code in the same manner as what is done via the static Configure method or perhaps have the ServiceHost ignore the configuration in some instances? (like when i create it my self).

I might very well be mixing concepts here but WCF is still a maze of configuration options to me.

A simple solution reproducing the error can be found here https://www.dropbox.com/s/e324vycbhkg5g5i/ReproduceWCFBindingIssue.zip?dl=0

Host the application and call the IAnotherService.DoStuff method on Service2.svc

Esben Bach
  • 664
  • 4
  • 23
  • You can also let the IIS/WAS component expose the named pipe binding. That way you have all 3 bindings in 1 service. See here for more info: http://stackoverflow.com/questions/16820022/binding-net-pipe-to-default-web-site-via-iis – Marc Selis Sep 23 '15 at 08:14
  • Yearh but then I would have to change the consuming code (the one creating the ServiceHost) to consume the service differently depending on if it was hosted in IIS/WAS or locally. That might very well be the best solution in the long run though. – Esben Bach Sep 23 '15 at 10:22

2 Answers2

0

Maybe I'm misreading you sample, but I think the problem is that your client and service code is mangled. Clients (the service consumers) should not create the service hosts themselves. Clients should limit themselves to creating a proxy for the service they want to talk to, and then interact with that proxy.

Hosting of the service should be done by a seperate component, possibly in a separate process.

If put the client address & binding information in config instead of in code, you can have the same component use the service with the wsHttpBindinding when running inside iis and use the service with the named pipe binding when running in another process.

Marc Selis
  • 833
  • 12
  • 17
  • Well the sample is a bit "fake" to illustrate the problem. But that is essentially what happens in my production code as well. My hosting process uses a library that is a client of the service that the hosting process exposes, but the client is built such that it hosts its own instance (some old idea about taking advantage of the behaviors and such that WCF provides when accessing via a proxy). It might be that our use case is so screwy that we need to re-engineer it - the current use case that fails was conveived a bit "by accident" anyway. – Esben Bach Sep 24 '15 at 10:32
0

Okay, I have been absent from the problem for a while, but finally figured the solution.

Its rather simple, I just disable httpGet and httpsGet on the host that I created internally, something like:

var host = new ServiceHost(typeof(Service1), new Uri("net.pipe://localhost/" + guid.ToString()));
var metadataBehavior = Description.Behaviors.Find<ServiceMetadataBehavior>();

if (metadataBehavior == null)
{
    return;
}

metadataBehavior.HttpGetEnabled = false;
metadataBehavior.HttpsGetEnabled = false;
host.Open(); // Now this won't throw an exception anymore.
Esben Bach
  • 664
  • 4
  • 23