I am following the code in the Launch Announcement Blog for RabbitMQ support in CoreWCF and am not sure what to do with this exception:
System.InvalidOperationException
HResult=0x80131509
Message=Contract requires TwoWay (either request-reply or duplex), but Binding 'RabbitMqBinding' doesn't support it or isn't configured properly to support it.
Source=System.ServiceModel.Primitives
StackTrace:
at System.ServiceModel.Channels.ServiceChannelFactory.BuildChannelFactory(ServiceEndpoint serviceEndpoint, Boolean useActiveAutoClose)
at System.ServiceModel.ChannelFactory.OnOpening()
at System.ServiceModel.Channels.CommunicationObject.<System-ServiceModel-IAsyncCommunicationObject-OpenAsync>d__88.MoveNext()
at System.ServiceModel.Channels.CommunicationObject.<OpenAsyncInternal>d__87.MoveNext()
at System.ServiceModel.ChannelFactory.EnsureOpened()
at System.ServiceModel.ChannelFactory`1.CreateChannel(EndpointAddress address, Uri via)
I created my Service following the CoreWCF Reademe:
dotnet new --install CoreWCF.Templates
dotnet new corewcf --name MyService
and this is my Contract:
[ServiceContract]
public interface IService
{
[OperationContract]
string GetData(int value);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
}
// Use a data contract as illustrated in the sample below to add composite types to service operations.
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
How do I change my Contract to support RabbitMQ Bindings?
I did try changing the contract so it had only void methods, and therefor doesn't need two-way communication, but I'm still getting the exception.
For additional context, this is the code that fails to create the Channel:
public static TContract CreateChannelOnRabbitMq<TContract>()
{
var endpointAddress = new System.ServiceModel.EndpointAddress(Uri);
var rabbitMqBinding = new CoreWCF.ServiceModel.Channels.RabbitMqBinding
{
SslOption = new SslOption
{
ServerName = Uri.Host,
Enabled = true
},
};
var factory = new ChannelFactory<TContract>(rabbitMqBinding, endpointAddress);
factory.Credentials.UserName.UserName = Credentials.UserName;
factory.Credentials.UserName.Password = Credentials.Password;
var channel = factory.CreateChannel();
(channel as System.ServiceModel.Channels.IChannel)?.Open();
return channel;
}
Turns out, I needed to mark the Operation Contracts as oneway:
System.ServiceModel.ServiceContract]
[CoreWCF.ServiceContract]
public interface IService
{
[System.ServiceModel.OperationContract(IsOneWay = true)]
[CoreWCF.OperationContract(IsOneWay = true)]
void SendData(int value);
}
Once marked up correctly I can send messages from the client and receive them on the server.