I have a WCF solution that consists of the following class libraries:
- Exercise.Services: Contains the implementation classes for the services.
- Exercise.ServiceProxy: Contains the classes that are instantiated in the client.
- Exercise.HttpHost: Contains the services (*.svc files).
I’m calling the service from a console application and the “first version” works really well so I took the next step which is to create a custom ServiceHostFactory, ServiceHost, and InstanceProvider so I can use constructor injection in my services as it is explained in this article.
These classes are implemented in yet another class library:
4. Exercise.StructureMapWcfExtension
Now even though I’ve modified my service this:
<%@ ServiceHost Language="C#" Debug="true" Factory="Exercise.StructureMapWcfExtension.StructureMapServiceHostFactory" Service="Exercise.Services.PurchaseOrderService" %>
I always get the following exception:
System.ServiceModel.CommunicationException Security negotiation failed
because the remote party did not send back a reply in a timely manner.
This may be because the underlying transport connection was aborted.
It fails in this line of code:
public class PurchaseOrderProxy : ClientBase<IPurchaseOrderService>, IPurchaseOrderService
{
public PurchaseOrderResponse CreatePurchaseOrder(PurchaseOrderRequest purchaseOrderRequest)
{
return base.Channel.CreatePurchaseOrder(purchaseOrderRequest); //Fails here
}
}
But that is not all, I added a trace to the web.config file and this is the error that appears in the log file:
System.InvalidOperationException The service type provided could not
be loaded as a service because it does not have a default
(parameter-less) constructor. To fix the problem, add a default
constructor to the type, or pass an instance of the type to the host.
So this means that my ServiceHostFactory is never being hit, I even set a breakpoint in both its constructor and its method and they never get hit.
I’ve added a reference of the StructureMapWcfExtension library to all the other ones (even the console client), one by one to no avail.
I also tried to use the option in the host’s web.config file to configure the factory like so:
<serviceHostingEnvironment>
<serviceActivations>
<add service="Exercise.Services.PurchaseOrderService" relativeAddress="PurchaseOrderService.svc" factory="Exercise.StructureMapWcfExtension.StructureMapServiceHostFactory"/>
</serviceActivations>
</serviceHostingEnvironment>
That didn’t work either.
Please I need help in getting this to work so I can incorporate it to our project.
Thank you.
UPDATE: Here’s the service host factory’s code:
namespace Exercise.StructureMapWcfExtension
{
public class StructureMapServiceHostFactory : ServiceHostFactory
{
private readonly Container Container;
public StructureMapServiceHostFactory()
{
Container = new Container();
new ContainerConfigurer().Configure(Container);
}
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new StructureMapServiceHost(Container, serviceType, baseAddresses);
}
}
public class ContainerConfigurer
{
public void Configure(Container container)
{
container.Configure(r => r.For<IPurchaseOrderFacade>().Use<PurchaseOrderFacade>());
}
}
public class StructureMapServiceHost : ServiceHost
{
public StructureMapServiceHost(Container container, Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
if (container == null) throw new ArgumentNullException("container");
var contracts = ImplementedContracts.Values;
foreach (var c in contracts)
{
var instanceProvider = new StructureMapInstanceProvider(container, serviceType);
c.Behaviors.Add(instanceProvider);
}
}
}
public class StructureMapInstanceProvider : IInstanceProvider, IContractBehavior
{
private readonly Container Container;
private readonly Type ServiceType;
public StructureMapInstanceProvider(Container container, Type serviceType)
{
if (container == null) throw new ArgumentNullException("container");
if (serviceType == null) throw new ArgumentNullException("serviceType");
Container = container;
ServiceType = serviceType;
}
public object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
return Container.GetInstance(ServiceType);
}
}
}
Looking at the code for StructureMapInstanceProvider, it looks like it is missing the setting of the dispatchRuntime.InstanceProvider. I copied the Listing 5 from your linked web page. It is part of the IContractBehavior interface.