Может ли непрерывный C# WebJob автоматически обрабатывать различные типы сообщений в одной очереди ServiceBus?
Я создал Azure WebJob для обработки двух разных пользовательских сообщений в одной очереди ServiceBus.
Поддерживается ли это автоматической десериализацией?
т.е. я могу просто создать две функции, каждая с одинаковым ServiceBusTrigger
но другой параметр сообщения:
public static void ProcessMessageA([ServiceBusTrigger("MessageQueue")] MessageA message) { ... }
public static void ProcessMessageB([ServiceBusTrigger("MessageQueue")] MessageB message) { ... }
Я пробовал это, но это не работает, поэтому я должен справиться BrokeredMessage
и вручную десериализовать и обработать сообщения в зависимости от ситуации?
2 ответа
Проблема в том, что SDK webjob не знает, какое сообщение имеет тип A или B.
Итак, как вы сказали, у вас есть возможность десериализации вручную сообщения брокера. Я думаю, что вы должны добавить свойство в ваше брокерское сообщение, чтобы указать тип сообщения.
Таким образом, чтобы отправить сообщение, это может быть что-то вроде этого:
// Create the object you want to send
var messageA = new MessageA();
...
// Create the borkered message
var message = new BrokeredMessage(messageA);
// Add a property
message.Properties["messageType"] = "MessageA";
// Send the message
...
Так что теперь у вас есть только одна функция в вашем веб-задании
public static void ProcessMessageA([ServiceBusTrigger("MessageQueue")] BrokeredMessage message)
{
var messageType = (string) message.Properties["messageType"];
if (messageType == "MessageA")
{
// Deserialize the message
var messageA = message.GetBody<MessageA>();
// Process the message
}
else if (messageType == "MessageB")
{
// Deserialize the message
var messageB = message.GetBody<MessageB>();;
// Process the message
}
}
В противном случае вы можете создать отдельные очереди для каждого типа сообщений или создать тему служебной шины с двумя подписками.
При создании подписки вы можете указать фильтр.
string connectionString = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");
var namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString);
// Create the topic
namespaceManager.CreateTopic("TestTopic");
// Create subscription to handle message A
namespaceManager.CreateSubscription("TestTopic", "MessageA", new SqlFilter("messageType = 'MessageA'"));
// Create subscription to handle message A
namespaceManager.CreateSubscription("TestTopic", "MessageB", new SqlFilter("messageType = 'MessageB'"));
Так что теперь вы можете иметь две разные функции в своем веб-задании для обработки MessageA и MessageB.
public static void ProcessMessageA([ServiceBusTrigger("TestTopic", "MessageA")] MessageA message) { }
public static void ProcessMessageB([ServiceBusTrigger("TestTopic", "MessageB")] MessageB message) { }
Попробуйте это: добавьте атрибут datacontract к определению вашего класса, например:
[DataContract(Namespace = "JobTransactionTopic.Notification")]
public class Notification
{
#region Public Properties
[DataMember]
public string Description { get; set; }
[DataMember]
public int LoginId { get; set; }
[DataMember]
public string Title { get; set; }
#endregion
}
Если ваши два класса отличаются, то, возможно, сериализатор сможет различить их. Важно, чтобы отправитель и получатель находились в одном и том же пространстве имен и чтобы определение класса было одинаковым для обеих сторон.
Дайте нам знать, если это поможет, мне интересно об этом.