1

Мы используем QueueClient Microsoft ServiceBus для отправки сообщения на служебную шину. При получении сообщения мы используем API-интерфейс ServiceBus REST. Дезериализация тела терпит неудачу, и мы не можем понять основную причину.Клиент REST клиента службы технической поддержки Microsoft - проблемы с чтением из очереди

Пример кода для отправки сообщения следующим образом:

MessagingFactory messagingFactory = 
    MessagingFactory.CreateFromConnectionString(....); 

Console.WriteLine("Creating Service Bus Queue Client..."); 

QueueClient queueSendClient = messagingFactory.CreateQueueClient(.); 

// Send message M1 to the topic. 
Console.WriteLine("Sending message.. "); 

BrokeredMessage bm = CreateMessage(); 
queueSendClient.Send(bm); 

CreateMessage создает экземпляр BrokeredMessage, который имеет экземпляр объекта сериализованную.

private static BrokeredMessage CreateMessage() 
{ 
    JObject o1 = JObject.Parse(File.ReadAllText(@"..\..\requestJson.json")); 

    string jsonMessage = JsonConvert.SerializeObject(o1); 

    CommandMessage commandMessage = new CommandMessage(); 
    JsonCommand content = new JsonCommand("abc", "def", jsonMessage); 

    List<Command> list = new List<Command>(); 
    list.Add(content); 
    commandMessage.Initialize(list, false, false); 

    var message = new BrokeredMessage(commandMessage); 

    return message; 
} 

Примечание: Команда CommandMessage, JsonCommand, Command украшена [DataContract].

Если мы также используем QueueClient для получения, то получение сообщения работает нормально. Но в нашем случае мы используем клиент Rest Service Service Rest.

Приемный код сообщения выглядит следующим образом:

объект
const string ServiceBusNamespace = "mysb2015-ns"; 
string baseAddressHttp = "https://" + ServiceBusNamespace + ".servicebus.windows.net/"; 
string queueAddress = baseAddressHttp + QueueName; 

HttpResponseMessage response = await this.httpClient.PostAsync(address + "/messages/head?timeout=60", new ByteArrayContent(new Byte[0])); 

byte[] body = response.Content.ReadAsByteArrayAsync().Result; 

DataContractSerializer deserializer = new DataContractSerializer(typeof(CommandMessage)); 
using (MemoryStream ms = new MemoryStream(body)) 
{ 
CommandMessage cmdMsg = (CommandMessage)deserializer.ReadObject(ms); 
} 

Считанные терпит неудачу с тем исключением, что данные на корневом уровне является недействительным:

System.Runtime.Serialization.SerializationException был необработанное HResult = -2146233076 Сообщение = Ошибка десериализации объекта типа CommandMessage. Данные на корневом уровне недействительны. Строка 1, позиция 1. Источник = System.Runtime.Serialization

Мы рассмотрели заголовок содержимого в ответе и это было application/xml; utf-8.

ответ

1

Инициализирует новый экземпляр класса BrokeredMessage из заданного объекта с помощью DataContractSerializer с бинарным XmlDictionaryWriter.

Когда вы отправляете BrokeredMessage в очередь, XmlDictionaryWriter добавляет свой тип индикации. Если вы используете QueueClient для получения, проблем не будет. Потому что он может разрешить этот тип индикации. Но если вы используете другой, чем QueueClient, у вас будет проблема с десериализацией.

Решение:

  1. Снимите индикатор перед тем десериализации.
  2. Используйте другой конструктор BrokeredMessage. BrokeredMessage(Stream messageBodyStream, bool ownsStream) и контролировать тело сообщения самостоятельно.

В этом article они объяснили проблему и ее решение.