I'm sending XML to an IBM MQ Queue that contains a CDATA section. That CDATA section contains these special characters: $§)#ÜÖ&!^. For some reason, they are showing up within the MQ Queue as $�)#��&!^. This causes the other send to take it off the queue with these characters and ending up having an invalid signature because the messages no longer match up.
We've verified that the message when we do a .Put() does contain an XML string with those special characters. I've ensured that the message has .CharacterSet property assigned to it that matches what we will eventually pull off the queue.
What other places can possibly be auto-encoding the special characters when it's put on the queue? Our application is in a .NET windows environment, but the MQ server is on a Linux box. Is this something to consider?
string xmlMsg = "<message><data><![CDATA[<value>$§)#ÜÖ&!^</value>]]</data></message>"; // This is in a CDATA section.
mQMessage = new MQMessage
{
CharacterSet = 1208,
};
mQMessage.WriteBytes(xmlMsg);
_queue.Put(mQMessage);
By default MQ doesn't change the character set of your message. So by default it is the responsibility of the sending and receiving applications to agree and maintain a character set that suits both.
You can request MQ to do character set conversion either in the receiving application, when that calls a get, or on the sender channels when the message is transmitted between queue managers. But even if you request character set conversion from MQ, it is still the sending applications responsibility to actually write the data into the message using the character set the application is setting on the MQ message header.
Based on your code it seems your sending application doesn't use the correct character set when it writes the bytes to the message. If you use WriteBytes, you need to manually convert the string into bytes using the desired character set.
I'd suggest you to use the WriteString method, which is designed to use the chracter set specified in the CharacterSet property:
The WriteString method converts from Unicode to the character set encoded in CharacterSet. If CharacterSet is set to its default value, MQC.MQCCSI_Q_MGR, which is 0, no conversion takes place and CharacterSet is set to 1200. If you set CharacterSet to some other value, WriteString converts from Unicode to the alternate value.
https://www.ibm.com/support/knowledgecenter/SSFKSJ_7.5.0/com.ibm.mq.ref.dev.doc/q111220_.htm
And by the way, for debugging character set issues you have to be very careful what tools you use to check the message, as your tool needs to be able to interpret the character set of the message. For example MQ Explorer uses the character set of your workstation where you run it, so it will show every message with that one character set, so is not suitable to debug these issues. The best is to get the message off the queue without asking the QM for conversion with rfhutil for example, save it to a file and look at it with a hex editor.
Related
I faced the problem of display message body. I send test message (using XmlFormatter) to queue using C# (I have Windows 7).
How can I remove hex from message body preview?
I found interesting moment: if body less 612 bytes - xml display is ok, but if body more 612 bytes - appears hex.
I can't use BinaryFormatter, because I need show in the message property (body) clear xml. (If use BinaryFormatter, hex displayed too).
I tried create custom (TxtFormatter) formatter - hex displayed too.
I found solution. Just need use ActiveXMessageFormatter
If you are using XmlMessageFormatter() while passing a non-XML string, you should ensure the following:
If message is an object, ensure that it has the attribute [Serializable]. Otherwise, the message body will be hexadecimal format.
Ensure the resulting serialized object attributes map correctly and have valid values, if defined in an XSD (XML Schema Definition) file.
Or you could use MSMQ Studio to view MSMQ messages. https://msmq-studio.com
The code that responds to a request is the following:
return new HttpStatusCodeResult(ex.Detail.HttpStatusCode, ex.Detail.ReasonPhrase);
Response.AddHeader("X-Status", ex.Detail.ReasonPhrase);
The funny thing here is that, on the browser/client, when there's a special char involved (such as ç or é) the reason phrase renders as expected, but the X-Status does NOT!!!
here's a screenshot for the non-believers
I've tested a uncountable number of encoding combinations but none worked... the X-Status just fails...
I have to use the X-Status custom header because Safari overrides whatever message comes with the StatusText...
The HTTP specification does not define a character encoding for header fields or the status line (well, not beyond US-ASCII). If you need non-ASCII characters, you're on your own. One reliable way is to percent-encode, for instance.
Also note that HTTP/2 doesn't have a status line, thus trying to use that to return information is a non-starter anyway.
I am Using IBM WebSphere MQ. Whenever simultaneous users log in to the IBM MQ, when the second user comes and try to access the getqueue they receive 2100 0x00000834 MQRC_OBJECT_ALREADY_EXISTS error. Kindly provide some suggestion.
Connect to MQ Manager:
mqQueueManager = new MQQueueManager(mqQueueManagerName);
Open Put Queue:
mqPutQueue = mqQueueManager.AccessQueue(mqRequestQueueName, MQC.MQOO_INQUIRE |
MQC.MQOO_OUTPUT | MQC.MQOO_FAIL_IF_QUIESCING);
Opening the ReplyTo Queue generates the error when the second user tries to connect. The First user's dynamic queue will be deleted when they disconnect. That Second user is unable to connect, until the first user closes the application:
mqGetQueue = mqQueueManager.AccessQueue(mqModelQueueName, MQC.MQOO_INPUT_SHARED ,
mqQueueManagerName, mqReplyQueueName, "");
You are probably specifying the dynamic queue name incorrectly.
To provide the greatest flexibility to developers, WebSphere MQ allows a choice between selecting the exact name you want for a dynamic queue or letting WebSphere MQ generate unique names automatically. If you want WebSphere MQ to generate the name for you, make sure the name you pass in is short enough to allow WMQ to append additional characters, and specify an asterisk as the last character in the DynamicQName field. This is explained in the docs in a section called Creating Dynamic Queues which reads as follows:
You can specify the name of the dynamic queue that you create in three ways:
Give the full name that you want in the DynamicQName field of the
MQOD structure.
Specify a prefix (fewer than 33 characters) for the
name, and allow the queue manager to generate the rest of the name.
This means that the queue manager generates a unique name, but you
still have some control (for example, you might want each user to use
a certain prefix, or you might want to give a special security
classification to queues with a certain prefix in their name). To use
this method, specify an asterisk () for the last non-blank character
of the DynamicQName field. Do not specify a single asterisk () for
the dynamic queue name.
Allow the queue manager to generate the full
name. To use this method, specify an asterisk (*) in the first
character position of the DynamicQName field.
Based on the behavior you are describing, I'm guessing there's no asterisk in the name that you are passing to WMQ. It therefore assumes you want to explicitly specify the name and does exactly what you specified, although perhaps not what you intended.
To get the behavior you expect, make sure the value you pass for mqReplyQueueName is a single asterisk (the '*' character), or is a string of less than 33 characters that ends with an asterisk.
Setup: I have a form built in asp.net/c# that, on submit, XML serializes it's object model and calls a stored procedure with that XML serialized data as the sole parameter. The stored procedure sends that data to a sql broker queue. The message sent to the broker queue must be valid XML that obeys the message contract set on the queue. That message is picked up by BizTalk and processed accordingly.
Problem: Originally the data submitted to me was just regular English characters (essentially held to ASCII charset) but a requirement is on the horizon to support foreign characters as well. In my testing, I've noticed that if I try to submit something with foreign characters (chinese, arabic, etc), I get an error in the queue and the message that gets to BizTalk ends up with "?????" in place of the foreign characters. I've added the utf=16 xml header to the top of the document, but that doesn't seem to help.
Question: Is there a way I can cast the incoming XML message as nvarchar and still have it be considered valid XML by the queue? I don't want to change the actual type on the queue or recreate it. I'd prefer to change the message in the stored proc alone in some way that allows it to get on the queue.
Thanks in advance for your help.
I ended up handling this by encoding the characters using HTML5 and then security escaping them. I ran into some issues using the HttpUtility library to handle this encoding so I added the method that I used to handle the encoding.
I wish I could give direct credit for this, I can't remember where I found this but thank you to whomever it was:
private string EncodeToHTML(string text)
{
// call the normal HtmlEncode first
char[] chars = HttpUtility.HtmlEncode(text).ToCharArray();
StringBuilder encodedValue = new StringBuilder();
foreach (char c in chars)
{
if ((int)c > 127) // above normal ASCII
encodedValue.Append("&#" + (int)c + ";");
else
encodedValue.Append(c);
}
return encodedValue.ToString();
}
We are working together with another firm. our application communicates with the other application through WCF on our side and a custom implemented java wsdl handler on the other side. They specify the wsdl format and one of the rules is that a specific string cannot contain more then 15 characters. (normally it's 60, but i take 15 for easy example reasons)
When we try to send the following string to them we get an error that the string is too long according to the wsdl:
"example & test" > this is a string of 14 characters, so it should be allowed
the microsoft wcf parser translates this to "example & test" . This encoded string is 18 characters long.
Now what is the standaard behavior to check a maxlength defined in a message? Is it the encoded message or the decoded message? I would think it's the decoded message , but i ain't sure. If it is the encoded message, how should we handle this so we would know how we have to split the string?
http://www.w3.org/TR/xmlschema-2/#rf-maxLength
4.3.3 maxLength
For string and datatypes ·derived· from string, maxLength is measured in units of characters as defined in [XML 1.0 (Second Edition)]
Charsets
[Definition: A parsed entity contains text, a sequence of characters, which may represent markup or character data.]
Reading that I would think the standard behaviour is the decoded as a marked up character should be treated as a single character.
So usually you do any splitting/truncation before you encode it.
Otherwise you run into issues if you truncate through the middle of an encoded character.
I've tested this against a WCF web service with BizTalk behind it and it's fine with an XML encoded string that is longer than the maxLength.
It sounds like they are doing it before the decode it though.
So you may have to encode it first and then split it on the white space.