Reputation: 468
I need to build a service that serves two interfaces. One interface uses basicHttpBinding, and the other should be netTcpBinding. The other one should also support duplex communication.
basicHttp interface:
[ServiceContract(Name = "accesspointService")]
[XmlSerializerFormat]
public interface IVERAAccessPoint
{
[OperationContract]
CompositeType GetDataUsingDataContract(MyClass obj);
}
Implementation:
[ServiceBehavior(Name = "accesspointService", Namespace = "http://www.w3.org/2009/02/ws-tra")]
public class VERAAccessPoint : IVERAAccessPoint
{
public CompositeType GetDataUsingDataContract(MyClass obj)
{
//something
return composite;
}
}
duplex netTcpContract:
[ServiceContract(CallbackContract = typeof(IClientCallback))]
public interface IVERAAPCS
{
[OperationContract(IsOneWay=true)]
void Subscribe(ClientInfo info);
[OperationContract(IsOneWay=true)]
void Unsubscribe(ClientInfo info);
}
public interface IClientCallback
{
[OperationContract(IsOneWay = true)]
void PushDocument(XDocument doc);
}
[DataContract]
public class ClientInfo
{
public string id;
}
And implementation:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,ConcurrencyMode = ConcurrencyMode.Single)]
public class VERAAPCS : IVERAAPCS
{
public void Subscribe(ClientInfo info)
{
//something
}
public void Unsubscribe(ClientInfo info)
{
//Something
}
}
I tried to self host both interfaces and this is the best i could do:
Uri baseAddress1 = new Uri("http://localhost:6544/hello");
//host the first interface
using (ServiceHost host = new ServiceHost(typeof(VERAAccessPoint.VERAAccessPoint), baseAddress))
{
// Enable metadata publishing.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
host.Open();
//Host the second (duplex interface)
using (ServiceHost host2 = new ServiceHost(typeof(VERAAccessPoint.VERAAPCS)))
{
host2.AddServiceEndpoint(typeof(VERAAccessPoint.IVERAAPCS), new NetTcpBinding(), "net.tcp://localhost:6543/hello2");
host2.Open();
Console.ReadLine();
host2.Close();
}
host.Close();
}
Now for the consuming part: //Consuming the first interface (this works so i removed it form the question) //Consuming the second interface:
var myBinding = new NetTcpBinding();
var myEndpoint = new EndpointAddress("net.tcp://localhost:6543/hello2");
var myChannelFactory = new ChannelFactory<VERAAccessPoint.IVERAAPCS>(myBinding, myEndpoint);
VERAAccessPoint.IVERAAPCS client = null;
client = myChannelFactory.CreateChannel();
This produces the following error:
ChannelFactory does not support the contract IVERAAPCS as it defines a callback contract with one or more operations. Please consider using DuplexChannelFactory instead of ChannelFactory.
But I just can't seem to find a way to use the duplexChannelFactory. So my question is basically how do you consume a duplex netTcpBinding service tat is self hosted?
Sorry for the long question, but I wanted to provide as much information as I could. Thanks
Upvotes: 1
Views: 2956
Reputation: 28530
Per your request in the comments, here's an example.
Place all of your interfaces in a separate assembly. For purposes of this example, let's name it ServiceContracts and use the namespace VERAAccessPoint.ServiceContracts
.
Inside this assembly (which you'll want to create as a class library - DLL), you place IVERAAccessPoint
, IVERAAPCS
, IClientCallback
and the data contract ClientInfo
.
Next, add add a reference to the ServiceContracts assembly in your self-hosted application and a using
directive:
using VerAAccessPoint.ServiceContracts;
That way you can implement the contract interfaces and host the services.
Finally, in your client application add the reference to the assembly and the using
directive, and then you can do the following:
IVERAAPCS client = null;
var myBinding = new NetTcpBinding();
var myEndpoint = new EndpointAddress("net.tcp://localhost:6543/hello2");
var myDuplexChannelFactory = new DuplexChannelFactory<IVERAAPCS>(myBinding, myEndpoint);
client = myDuplexChannelFactory.CreateChannel();
You could do something similar with ChannelFactory<T>
using IVERAAccessPoint
as well.
I have used ChannelFactory<T>
a lot, but never the DuplexChannelFactory<T>
, but this should give you another option to explore.
Upvotes: 1