Reputation: 129
I've searched and wasted all day trying everything I can think of or find to resolve this issue: I built my first WCF service and thought it would be cool to host it in IIS. It's a long-running service, so that's a no-go. I have since added another project to my solution to host the WCF service with, referenced the WCF project, and have been met with constant struggle trying to host from code. I largely followed http://msdn.microsoft.com/en-us/library/ms733069.aspx for guidance on implementing the host, with minor tweaks for my specific situation.
The current challenge is simply getting the service endpoint defined in the hosting project's App.config. It cannot resolve the "contract" attribute of an "endpoint" to my WCF service contract.
WCF Assembly
namespace WcfFoldingService
{
[ServiceContract(SessionMode=SessionMode.Required, CallbackContract=typeof(IFoldingUpdaterClientContract))]
public interface IFoldingUpdaterServiceBehavior
{
[OperationContract(IsOneWay = false, IsInitiating = true)]
void Subscribe();
[OperationContract(IsOneWay = false, IsTerminating = true)]
void Unsubscribe();
[OperationContract(IsOneWay = true)]
void PublishSomeOperation();
}
public interface IFoldingUpdaterClientContract
{
[OperationContract(IsOneWay = true)]
void SomeOperation();
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession, ConcurrencyMode=ConcurrencyMode.Single)]
public class FoldingUpdaterService : IFoldingUpdaterServiceBehavior
{
// Omitted for brevity, but complete implementation exists.
}
}
/WCF Assembly
Hosting Assembly
App.config
<system.serviceModel>
<services>
<service name="WcfFoldingService.FoldingUpdaterService" behaviorConfiguration="httpServiceBehavior">
<endpoint address="" binding="wsDualHttpBinding" bindingConfiguration="ServiceBindingConfiguration" contract="WcfFoldingService.IFoldingUpdaterServiceBehavior"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<protocolMapping>
<add scheme="http" binding="wsDualHttpBinding" bindingConfiguration="ServiceBindingConfiguration"/>
</protocolMapping>
<bindings>
<wsDualHttpBinding>
<binding name="ServiceBindingConfiguration">
<reliableSession ordered="true"/>
<security mode="None"/>
</binding>
</wsDualHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="httpServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
<serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="100" maxConcurrentSessions="100"/>
<sendMessageChannelCache allowUnsafeCaching="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
/Hosting Assembly
Message:
The 'contract' attribute is invalid - The value 'WcfFoldingService.IFoldingUpdaterServiceBehavior' is invalid according to its datatype 'serviceContractType' - The Enumeration constraint failed.
I'm stumped. Google offers few relevant links, and they mostly have to do with other configuration issues that I am not experiencing. The WCF assembly is referenced, I am using fully qualified names, I even tried using the ConfigurationName attribute in case there was a namespace conflict somehow. I'm new to WCF so I'm hopeful that this is an obvious problem!
Edit:
I am now using programmatic configuration rather than App.config XML. The most significant statement is ContractDescription.GetContract(serviceType)
, as even new ContractDescription("FullNamespace.IContract")
failed exactly as the XML configuration did. The Type object for serviceType's FullName property is exactly the same as my "FullNamespace.IContract". I suspect an issue with the assembly not being loaded without a hard reference to it in code, but I cannot be certain at this point. For now, this approach will work fine:
using (var host = new ServiceHost(typeof(FoldingUpdaterService), baseAddress))
{
var serviceType = typeof (IFoldingUpdaterServiceBehavior);
var serviceContract = ContractDescription.GetContract(serviceType);
var foldingEndpoint = new ServiceEndpoint(serviceContract)
{
Binding = new WSDualHttpBinding()
Address = new EndpointAddress(new Properties.Settings().WcfUpdaterServiceAddress)
};
host.Description.Endpoints.Add(foldingEndpoint);
[...]
Upvotes: 2
Views: 6794
Reputation: 21
My solution, created with VS2012, contained several .NET 4.0 projects. I switched to VS2013, and when I added a new WCF library project, it was created with .NET 4.5. Resetting the new projects to .NET 4.0 solved my problem.
Upvotes: 0
Reputation: 371
This is an old question, but in case someone has the same problem, this worked for me: Try closing Visual Studio and deleting the .suo file located at the same directory as your solution file (.sln). This resets the editors cache. I had the same problem after I moved the service contract file to a different assembly and the cache still referred to the old location.
Upvotes: 3
Reputation: 136
I don't know if this still an issue to you, but stumbled upon the same problem recently and it might be of some help.
When specifying your Service Name, you have to use your Namespace as well. So lets say your Namespace would be myhost
then the correct entry would be ...
<service name="myhost.WcfFoldingService.FoldingUpdaterService"...>
The same applies to the contract.
Upvotes: 0
Reputation: 1
Make sure that you made a Reference of the service application in the host
Upvotes: -1
Reputation: 126
The self-hosting application will need <host>
tag inside <service>
tag:
<system.serviceModel>
<services>
<service name="WcfFoldingService.FoldingUpdaterService" behaviorConfiguration="httpServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/Services/"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsDualHttpBinding" bindingConfiguration="ServiceBindingConfiguration" contract="WcfFoldingService.IFoldingUpdaterServiceBehavior"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
Upvotes: 1