Может ли непрерывный 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
}

Если ваши два класса отличаются, то, возможно, сериализатор сможет различить их. Важно, чтобы отправитель и получатель находились в одном и том же пространстве имен и чтобы определение класса было одинаковым для обеих сторон.

Дайте нам знать, если это поможет, мне интересно об этом.

Другие вопросы по тегам