I am sending a csv file to an Azure Service Bus Queue from a .NET 3.5 based C# solution. Since the Service Bus nuget packages aren't available in .NET 3.5, I am using the Rest API.
byte[] file = File.ReadAllBytes(@"VehicleContacts.csv");
string url = baseAddress + queueName + "/messages" + "?timeout=60&api-version=2013-08 ";
WebClient webClient = new WebClient();
webClient.Proxy = proxy;
webClient.Headers[HttpRequestHeader.Authorization] = token;
// Add Broker Properties
webClient.Headers.Add("BrokerProperties", "{ \"Label\":\"VehicleContactsSync\" }");
// Add Custom Properties
webClient.Headers.Add("FileName", "VehicleContactsSyncFile");
webClient.UploadData(url, "POST", file);
The queue receives the file properly. On the receiving side, I can use .NET 4.5. So, I try to get the message body using the following code:
BrokeredMessage message = queueClient.Receive(TimeSpan.FromSeconds(5));
if (message != null)
{
var contentType = message.ContentType;
var body = message.GetBody<byte[]>();
}
Here I get the contentType as byte[] as expected. But when I try to get the Body, I get the following error:
System.Runtime.Serialization.SerializationException occurred
HResult=0x8013150C
Message=There was an error deserializing the object of type System.Byte[].
The input source is not correctly formatted.
Source=System.Runtime.Serialization
StackTrace:
at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.DataContractSerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObject(XmlDictionaryReader reader)
at Microsoft.ServiceBus.Messaging.BrokeredMessage.GetBody[T](XmlObjectSerializer serializer)
Inner Exception 1:
XmlException: The input source is not correctly formatted.
What am I doing wrong and how can I fix it?
XmlException: The input source is not correctly formatted.
According to your discription, we could know the body formatted is incorrect. In your case, it seem that you use the CSV format file.
From the document, we could know that BrokeredMessage.GetBody<T>
Method that deserializes the brokered message body into an object of the specified type by using the System.Runtime.Serialization.DataContractSerializer
with a binary System.Xml.XmlDictionaryReader
.
What am I doing wrong and how can I fix it?
According to the Azure service bus send message API, we know that we need to use the Xml format message body.
So please have a try to change the file to the xml format then it will be solved.
Edit:
Please have a try to DataContractSerializer your data before you send it
MemoryStream ms = new MemoryStream();
DataContractSerializer serializer = new DataContractSerializer(typeof(byte[]));
serializer.WriteObject(ms, file);
byte[] body = ms.ToArray();
WebClient webClient = new WebClient { Headers = { [HttpRequestHeader.Authorization] = token } };
// Add Broker Properties
webClient.Headers.Add("BrokerProperties", "{ \"Label\":\"VehicleContactsSync\" }");
// Add Custom Properties
webClient.Headers.Add("FileName", "VehicleContactsSyncFile");
webClient.UploadData(queueUrl, "POST", body);
I did a demo for it, it works correctly on my side.
1.Create a console project
2.Create token for sending message
public static string GetSasToken(string resourceUri, string keyName, string key, TimeSpan ttl)
{
var expiry = GetExpiry(ttl);
string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;
HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
var sasToken = String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
HttpUtility.UrlEncode(resourceUri), HttpUtility.UrlEncode(signature), expiry, keyName);
return sasToken;
}
private static string GetExpiry(TimeSpan ttl)
{
TimeSpan expirySinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1) + ttl;
return Convert.ToString((int)expirySinceEpoch.TotalSeconds);
}
3.add creating queue function
public static void CreateQueue()
{
var cs = "connection string";
var queueName = "queuename";
var namespaceManager = NamespaceManager.CreateFromConnectionString(cs);
var messagingFactory = MessagingFactory.CreateFromConnectionString(cs);
var ver = namespaceManager.GetVersionInfo();
if (namespaceManager.QueueExists(queueName))
{
namespaceManager.DeleteQueue(queueName);
}
namespaceManager.CreateQueue(queueName);
}
4.add receiving queue message function
public static void ReceiveMessage()
{
BrokeredMessage message = queueClient.Receive();
if (message != null)
{
var body = message.GetBody<byte[]>(new DataContractSerializer(typeof(byte[])));
Console.WriteLine(body);
}
Console.ReadKey();
}
5. add sending message with http function
public static void SendHttpMessage()
{
byte[] file = File.ReadAllBytes(@"C:\tom\test.txt");
string queueUrl = "https://servicebusname.servicebus.windows.net/" + "SampleQueue" + "/messages?timeout=60&api-version=2013-08";
string token = GetSasToken(queueUrl,
"Key name", "Key", TimeSpan.FromDays(1));
MemoryStream ms = new MemoryStream();
DataContractSerializer serializer = new DataContractSerializer(typeof(byte[]));
serializer.WriteObject(ms, file);
byte[] body = ms.ToArray();
WebClient webClient = new WebClient { Headers = { [HttpRequestHeader.Authorization] = token } };
// Add Broker Properties
webClient.Headers.Add("BrokerProperties", "{ \"Label\":\"VehicleContactsSync\" }");
// Add Custom Properties
webClient.Headers.Add("FileName", "VehicleContactsSyncFile");
webClient.UploadData(queueUrl, "POST", body);
}
6.Test in the main function
private static QueueClient queueClient;
static void Main(string[] args)
{
CreateQueue();
SendHttpMessage();
ReceiveMessage();
}
7.During send message I use fiddler to catch the http request, detail please refer to the screenshot. We can see that the sent message has been formatted
Package.config file
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="WindowsAzure.ServiceBus" version="4.0.0" targetFramework="net452" />
</packages>
User contributions licensed under CC BY-SA 3.0