NetMessagingBinding始終使用BinaryMessageEncodingBindingElement + NetMessagingTransportBindingElement構建通道堆棧。如果ServiceBus隊列/訂閱中的BrokeredMessages是普通的[text] xml,那麼BinaryMessageEncoding將不起作用,使用WCF您將使用帶有TextMessageEncoder和NetMessagingTransportBindingElement的CustomBinding。
總之,您需要使用帶有TextMessageEncodingBindingElement(具有MessageVersion = None)的CustomBinding和NetMessagingTransportBindingElement,確保Action =「*」,並在您的ServiceBehavior上設置AddressFilterMode = Any。
下面是使用NetMessagingTransportBindingElement讀一個普通的舊XML消息兩種方式:
解決方案#1 使用System.ServiceModel.Channels.Message中的ServiceContract和調用Message.GetBody()
namespace MessagingConsole
{
static class Constants {
public const string ContractNamespace = "http://contoso";
}
[DataContract(Namespace = Constants.ContractNamespace)]
class Record
{
[DataMember]
public string Id { get; set; }
}
[ServiceContract]
interface ITestContract
{
[OperationContract(IsOneWay = true, Action="*")]
void UpdateRecord(Message message);
}
[ServiceBehavior(
AddressFilterMode = AddressFilterMode.Any)] // This is another way to avoid 「The message with To 」 cannot be processed at the receiver…」
class TestService : ITestContract
{
[OperationBehavior]
public void UpdateRecord(Message message)
{
Record r = message.GetBody<Record>();
Console.WriteLine("UpdateRecord called! " + r.Id);
}
}
class ServiceProgram
{
static void Main(string[] args)
{
string solution = "sb://SOMENS";
string owner = "owner";
string key = "XXXXXX=";
string topicPath = "Topic2";
string subscriptionName = "Sub0";
TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider(owner, key);
MessagingFactory factory = MessagingFactory.Create(solution, tokenProvider);
TopicClient sender = factory.CreateTopicClient(topicPath);
SubscriptionClient receiver = factory.CreateSubscriptionClient(topicPath, subscriptionName, ReceiveMode.ReceiveAndDelete);
string interopPayload = "<Record xmlns='" + Constants.ContractNamespace + "'><Id>4</Id></Record>";
BrokeredMessage interopMessage = new BrokeredMessage(new MemoryStream(Encoding.UTF8.GetBytes(interopPayload)), true);
sender.Send(interopMessage);
CustomBinding binding = new CustomBinding(
new TextMessageEncodingBindingElement { MessageVersion = MessageVersion.None },
new NetMessagingTransportBindingElement());
ServiceHost serviceHost = new ServiceHost(typeof(TestService), new Uri(solution));
ServiceEndpoint endpoint = serviceHost.AddServiceEndpoint(typeof(ITestContract), binding, topicPath + "/Subscriptions/" + subscriptionName);
endpoint.Behaviors.Add(new TransportClientEndpointBehavior(tokenProvider));
serviceHost.Open();
Console.WriteLine("Service is running");
Console.ReadLine();
}
}
}
解決方案#2 定義MessageContract數據類型,來使預期肥皂合同匹配什麼互操作的客戶端發送:
namespace MessagingConsole
{
static class Constants
{
public const string ContractNamespace = "http://contoso";
}
[DataContract(Namespace = Constants.ContractNamespace)]
class Record
{
[DataMember]
public string Id { get; set; }
}
[MessageContract(IsWrapped=false)]
class RecordMessageContract
{
[MessageBodyMember(Namespace = Constants.ContractNamespace)]
public Record Record { get; set; }
}
[ServiceContract]
interface ITestContract
{
[OperationContract(IsOneWay = true, Action="*")]
void UpdateRecord(RecordMessageContract recordMessageContract);
}
class ServiceProgram
{
static void Main(string[] args)
{
string solution = "sb://SOMENS";
string owner = "owner";
string key = "XXXXXXXXXXXXXX=";
string topicPath = "Topic2";
string subscriptionName = "Sub0";
TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider(owner, key);
MessagingFactory factory = MessagingFactory.Create(solution, tokenProvider);
TopicClient sender = factory.CreateTopicClient(topicPath);
SubscriptionClient receiver = factory.CreateSubscriptionClient(topicPath, subscriptionName, ReceiveMode.ReceiveAndDelete);
string interopPayload = "<Record xmlns='" + Constants.ContractNamespace + "'><Id>5</Id></Record>";
BrokeredMessage interopMessage = new BrokeredMessage(new MemoryStream(Encoding.UTF8.GetBytes(interopPayload)), true);
sender.Send(interopMessage);
CustomBinding binding = new CustomBinding(
new TextMessageEncodingBindingElement { MessageVersion = MessageVersion.None },
new NetMessagingTransportBindingElement());
ServiceHost serviceHost = new ServiceHost(typeof(TestService), new Uri(solution));
ServiceEndpoint endpoint = serviceHost.AddServiceEndpoint(typeof(ITestContract), binding, topicPath + "/Subscriptions/" + subscriptionName);
endpoint.Behaviors.Add(new TransportClientEndpointBehavior(tokenProvider));
serviceHost.Open();
Console.WriteLine("Service is running");
Console.ReadLine();
}
}
[ServiceBehavior(
AddressFilterMode = AddressFilterMode.Any
)]
class TestService : ITestContract
{
[OperationBehavior]
public void UpdateRecord(RecordMessageContract recordMessageContract)
{
Record r = recordMessageContract.Record;
Console.WriteLine("UpdateRecord called! " + r.Id);
}
}
}