How to use .NET LLRP Library : Org.LLRP.LTK.LLRPV1.LLRPXmlParser.ParseXMLToLLRPMessage - c#

I am developing an application using LLRP library.
After gateway(computer) receive my message from reader(simulated reader using localhost) I would like to convert it to LLRPMessage using
Org.LLRP.LTK.LLRPV1.LLRPXmlParser.ParseXMLToLLRPMessage(_xmlReceived, out msg, out enumType);
However, I check it in the watch(VS2013 Ultimate): msg is null and enumType is 0.
May I have your advice on this?
My code is :
public static void ConvertXmlToLLRPMessage()
{
Org.LLRP.LTK.LLRPV1.DataType.Message msg; //Only Message type is accepted.
Org.LLRP.LTK.LLRPV1.ENUM_LLRP_MSG_TYPE enumType; //Only ENUM_LLRP_MSG_TYPE type is accepted.
Org.LLRP.LTK.LLRPV1.LLRPXmlParser.ParseXMLToLLRPMessage(_xmlReceived, out msg, out enumType);
Console.WriteLine();
Console.WriteLine("Print out _xmlReceived, inside ConvertXmlToLLRPMessage.");
Console.WriteLine(_xmlReceived);
Console.WriteLine();
Console.WriteLine("Out msg from ParseXMLToLLRPMessage:\n"); Console.WriteLine(msg); Console.WriteLine();
Console.WriteLine("Out enumType from ParseXMLToLLRPMessage:\n"); Console.WriteLine(enumType); Console.WriteLine();
}
_xmlReceived is the XML-converted data receive from 127.0.0.1 :5084. I have to check it and it is correct it is what the reader sent out.
On Reader side, I simulate the reader to send a message to the gateway.
On reader side, the code is :
public static void testData_PARAM_ROSpecID()
{
//create and object
PARAM_ROSpecID _rec_PARAM_ROSpecID = new PARAM_ROSpecID();
//assign value to an object
_rec_PARAM_ROSpecID.ROSpecID = 789;
//Convert obj to xml
string _xmlData = ConvertObjectToXml(_rec_PARAM_ROSpecID);
//Convert xml to byte array
byte [] _byteArray = CommServerSend.getSendBuffInByteAry(_xmlData);
//Send out.
CommServerReceive._incomingDataObj.Send(_byteArray);
return;
}
Print out of data reader send out to gateway :
<?xml version="1.0" encoding="utf-16"?>
<PARAM_ROSpecID xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ROSpecID>789</ROSpecID>
</PARAM_ROSpecID>
Print out of data gateway receive from reader:
<?xml version="1.0" encoding="utf-16"?>
<PARAM_ROSpecID xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ROSpecID>789</ROSpecID>
</PARAM_ROSpecID>
but after process it using Org.LLRP.LTK.LLRPV1.LLRPXmlParser.ParseXMLToLLRPMessage(_xmlReceived, out msg, out enumType); and print out msg and enumType:
Out msg from ParseXMLToLLRPMessage:
Out enumType from ParseXMLToLLRPMessage: 0
Please help me and reply soon.
Your effort is very much appreciated.

The null obj variable would mean that the Method was unable to extract the message from the xml passed in. I would look more closely at the xml to see if there is something wrong there.
Here is an example of how the code should look for using ParseXMLToLLRPMessage():
Org.LLRP.LTK.LLRPV1.DataType.Message obj;
ENUM_LLRP_MSG_TYPE msg_type;
// read the XML from a file and validate its an SET_READER_CONFIG
try
{
FileStream fs = new FileStream(#"setReaderConfig.xml", FileMode.Open);
StreamReader sr = new StreamReader(fs);
string s = sr.ReadToEnd();
fs.Close();
LLRPXmlParser.ParseXMLToLLRPMessage(s, out obj, out msg_type);
if (obj == null || msg_type != ENUM_LLRP_MSG_TYPE.SET_READER_CONFIG)
{
Console.WriteLine("Could not extract message from XML");
return;
}
}
catch
{
Console.WriteLine("Unable to convert to valid XML");
return;
}
// Communicate that message to the reader
MSG_SET_READER_CONFIG msg = (MSG_SET_READER_CONFIG)obj;

Related

How to deserialize string that get from Stream using c#?

I have an API which handles call back event of HelloSign. I get Stream in the request data. I convert that Stream into String using following code and it provide me following string.
public bool HSEventCallback(Stream stream)
{
bool callbackStatus = false;
try
{
StreamReader reader = new StreamReader(stream);
string text = reader.ReadToEnd();
callbackStatus = true;
}
catch (Exception ex)
{
callbackStatus = false;
}
return callbackStatus;
}
Result
------------------------------5sdf54df6a5s4df6 Content-Disposition: form-data; name="json"
{"event":{"event_type":"callback_test","event_time":"514651651","event_hash":"65a65adsxv34adsv514dv6514v6s584v6a5v46a5sv46sd5v146v54s6av4s6av54ds6v46av","event_metadata":{"related_signature_id":null,"reported_for_account_id":"564as4df65a4f65sd4f65sad4f6sad5f46sdf54s6df54","reported_for_app_id":null,"event_message":null}}}
------------------------------5sdf54df6a5s4df6--
Can anybody please suggest me how to de serialize above string. I can deserialize by replacing some of text and by creating class of `event'. But I don't know whether it will work for all kind of data.
Please suggest standard way to deserialize above string.

MSMQ Save Failed MessageBody to Text File

I'm writing a Windows Service to listen and process messages from MSMQ. The listener has various error handling steps, but if all else fails, I want to save the body of the message to a text file so that I can look at it. However, I can't seem to extract the content of my messages when this condition is hit. The following code is a simple representation of the sections in question, and it always produces an empty text file even though I know the message I'm testing with is not empty. HOWEVER, if I comment-out the initial attempt to deserialize the XML, the fail safe does work and produces a text file with the message body. So I think the problem is something to do with how the deserialization attempt leaves the underlying Stream? Just to clarify, when the message contains valid XML that CAN be deserialized, the service all works fine and the fail-safe never comes into action.
MyClass myClass = null;
try
{
XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
// Comment the following out and the fail safe works
// Let this run and fail and the text file below is always empty
myClass = (MyClass)serializer.Deserialize(m.BodyStream);
}
catch (Exception ex)
{
}
if (myClass == null)
{
string filePath = #"D:\path\file.txt";
m.Formatter = new ActiveXMessageFormatter();
StreamReader reader = new StreamReader(m.BodyStream);
File.WriteAllText(filePath, reader.ReadToEnd());
}
Depending on the formatter you are using:
For windows binary messages:
File.WriteAllText(<path>, (new UTF8Encoding()).GetString((byte[])msg.Body)); // for binary
For XML messages try this:
msg.Formatter = new XmlMessageFormatter(new String[] { "System.String, mscorlib" });
var text = msg.Body.ToString();
// write to file..
For neither binary or XML, use the native formatter:
msg.Formatter = new ActiveXMessageFormatter();
reader = new StreamReader(msg.BodyStream);
msgBody = reader.ReadToEnd();
// write to file..

HttpResponseMessage fails to deserialize XML but filestream is fine

I'm trying to consume a third party webservice. I craft a request message, send it to the httpclient and receive the httpResponseMessage.
Below is a snippet from the method that handles the call. xml = true for my situation.
HttpResponseMessage response = await HttpClientInstance.SendAsync(requestMessage);
if (response.IsSuccessStatusCode)
{
if (xml)
{
try
{
//This fails with "the data at the root level is invalid"
XmlMediaTypeFormatter xmlFormatter = new XmlMediaTypeFormatter { UseXmlSerializer = true };
var content = response.Content.ReadAsAsync<T>(new Collection<MediaTypeFormatter> { xmlFormatter });
return content.Result;
}
catch (Exception tempe)
{
var content = response.Content.ReadAsAsync<T>();
return content.Result;
}
}
else
{
var content = response.Content.ReadAsAsync<T>();
return content.Result;
}
}
else
{
_logWriter.LogProcessFault(operationContext, null, GetCurrentMethod(), $"An error occurred while calling the API. URI = {endpoint}. StatusCode = {response.StatusCode}", null);
throw new Exception(response.StatusCode.ToString());
}
After running this code, an error is thrown when attempting to deserialize the XML data in the stream. It fails with an error "the data at the root level is invalid".
I commented out the XMLMediaTypeFormatter and response.Content.Read... and replaced it with this
var fileStream = File.Create("D:\\Extract\\test.txt");
await response.Content.CopyToAsync(fileStream);
fileStream.Close();
which writes out valid XML to a file.
In the immediate window I ran response.Content.ReadAsStringAsync() and the returned string value has extra backslashes escaping content.
For instance, this is what is in the generated test.txt file:
<?xml version="1.0" encoding="utf-8"?>
and this is from ReadAsStringAsync:
<?xml version=\"1.0\" encoding=\"utf-8\"?>
I believe this is what is causing the deserialization to fail. Is there a clean fix for this or perhaps I am doing something wrong elsewhere?
The issue is in the following block of code
await response.Content.CopyToAsync(fileStream);
fileStream.Close();
//This fails with "the data at the root level is invalid"
XmlMediaTypeFormatter xmlFormatter = new XmlMediaTypeFormatter { UseXmlSerializer = true };
var content = response.Content.ReadAsAsync<T>(new Collection<MediaTypeFormatter> { xmlFormatter });
HTTP responses can be consumed only once. In other words, response is not read into some buffer from which multiple reads can be serviced. It reads it directly off of the socket. So once read, it cannot be read again.
Above, you copy response into a file. That consumes the response and it is no longer available to be read again. So by the time you try to read it again when assigning to content, it reads nothing, so the XML parser (in formatter) throws xml syntax error b/c it basically receives an empty string.
Not sure why you're saving to file, but once saved to file, you can simply read the file and send its contents to xml parser, and your code should now work. And of course if you remove saving to file, you should be able to read and parse contents of the response just fine.

System.ServiceModel.CommunicationException when parsing WCF ProtocolException

I am trying to use the recommended code from this page http://blogs.msdn.com/b/nathana/archive/2011/03/31/deciphering-a-soap-fault-with-a-400-status-code.aspx as follows:
static FaultException ParseProtocolExecption(ProtocolException ex)
{
try
{
System.IO.Stream stream = (ex.InnerException as WebException).Response.GetResponseStream();
System.Xml.XmlReader xmr = System.Xml.XmlReader.Create(stream);
Message message = Message.CreateMessage(xmr, (int)stream.Length, MessageVersion.Soap12);
MessageFault mf = MessageFault.CreateFault(message, (int)stream.Length);
FaultException fe = new FaultException(mf);
message.Close();
return fe;
}
catch (Exception)
{
return new FaultException(ex.Message);
}
}
I am using VS 2012 with .NET 4.5 using WCF. When the app gets a 400 Bad Request and it passes the ProtocolException to ParseProtocolException, it throws an exception on this line:
Message message = Message.CreateMessage(xmr, (int)stream.Length, MessageVersion.Soap12);
with the System.ServiceModel.CommunicationException: "The size necessary to buffer the XML content exceeded the buffer quota."
The stream.Length = 2,704 bytes, which is not very big. I tried the solution suggested on this site http://blogs.msdn.com/b/drnick/archive/2007/08/07/increasing-the-maximum-fault-size.aspx. However, even with the MaxFaultSize = 1 Mb, it gets the same errror.
Instead of this line:
System.Xml.XmlReader xmr = System.Xml.XmlReader.Create(stream);
I've tried this:
xmr = XmlDictionaryReader.CreateTextReader(stream, XmlDictionaryReaderQuotas.Max);
which sets all the quotas to their maximum value (Int32.MaxValue); but, I still get the same error on the CreateMessage call.
A sample response stream from the System.Net.WebException is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa5="http://www.w3.org/2005/08/addressing" xmlns:c14n="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:xmime5="http://www.w3.org/2005/05/xmlmime" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" xmlns:tds2="http://www.onvif.org/ver10/schema" xmlns:tds3="http://docs.oasis-open.org/wsn/b-2" xmlns:tds4="http://docs.oasis-open.org/wsrf/bf-2" xmlns:tds5="http://docs.oasis-open.org/wsn/t-1" xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl" xmlns:tds6="http://www.canon.com/ns/networkcamera/onvif/va/schema" xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl" xmlns:tev="http://www.onvif.org/ver10/events/wsdl" xmlns:tds9="http://docs.oasis-open.org/wsrf/r-2" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:ter="http://www.onvif.org/ver10/error">
<SOAP-ENV:Header></SOAP-ENV:Header>
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<SOAP-ENV:Code>
<SOAP-ENV:Value>SOAP-ENV:Sender</SOAP-ENV:Value>
<SOAP-ENV:Subcode>
<SOAP-ENV:Value>ter:NotAuthorized</SOAP-ENV:Value>
</SOAP-ENV:Subcode>
</SOAP-ENV:Code>
<SOAP-ENV:Reason>
<SOAP-ENV:Text xml:lang="en">Sender Not Authorized</SOAP-ENV:Text>
</SOAP-ENV:Reason>
<SOAP-ENV:Node>http://www.w3.org/2003/05/soap-envelope/node/ultimateReceiver</SOAP-ENV:Node>
<SOAP-ENV:Role>http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver</SOAP-ENV:Role>
<SOAP-ENV:Detail>The action requested requires authorization and the sender is not authorized</SOAP-ENV:Detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Using an async web crawler that I wrote in F# Interactive, I found that some of the namespace url's were not resolvable. I corrected the erroneous ones and then ran the crawler again to sum the lengths of the namespace pages. The total is 715,965 bytes, which is much less than the Int32.MaxValue of all the quotas in XmlDictionaryReaderQuotas. Perhaps the XmlDictionaryReader has a bug, or the error it returns is not the real problem?
I finally got the Message creation to work by removing the namespace definitions that were not actually used in the SOAP-ENV:Body (i.e., keeping only the xmlns:ter used in the Subcode element). But, of course, this doesn't really solve the problem, because the service is generating the SOAP fault; and I cannot change the service implementation (it's a 3rd party device - an Onvif camera).
Morevover, I can't make the quotas any greater; so, how else to handle this exception?
The solution is to trap the CommunicationException and then do an alternate parse of the XML in the stream that doesn't require namespace resolution:
public static FaultException ParseProtocolException(System.ServiceModel.ProtocolException ex) {
var stream = (ex.InnerException as System.Net.WebException).Response.GetResponseStream();
try {
var xmr = XmlReader.Create(stream);
var message = Message.CreateMessage(xmr, (int)stream.Length, MessageVersion.Soap12);
var mf = MessageFault.CreateFault(message, (int)stream.Length);
message.Close();
return new FaultException(mf);
} catch (CommunicationException) { // If CreateMessage has a problem parsing the XML,
// then this error will be thrown. Most likely, there is an unresolvable namespace reference.
// Do an alternate parse
stream.Seek(0, System.IO.SeekOrigin.Begin);
var soapFault = GetSoapFault(stream);
return new FaultException(soapFault.Reason);
}
}
The catch resets the stream to the beginning and then uses the following to get the specifics of the SOAP Fault using an XmlReader:
private struct SoapFault {
public string Subcode;
public string Reason;
public string Detail;
}
private static string GetTextChild(XmlReader xmr, string childName) {
return xmr.ReadToDescendant(childName) ?
xmr.ReadString() : System.String.Empty;
}
private static SoapFault GetSoapFault(System.IO.Stream s) {
var xr = XmlReader.Create(s);
var fault = new SoapFault();
if (xr.ReadToFollowing("SOAP-ENV:Subcode")) {
fault.Subcode = GetTextChild(xr, "SOAP-ENV:Value");
if (xr.ReadToFollowing("SOAP-ENV:Reason")) {
fault.Reason = GetTextChild(xr, "SOAP-ENV:Text");
if (xr.ReadToFollowing("SOAP-ENV:Detail"))
fault.Detail = GetTextChild(xr, "SOAP-ENV:Text");
}
}
return fault;
}

Getting answer from Jabber Server

I want connect with my jabber server and read server answer:
DnsEndPoint host = new DnsEndPoint("talk.google.com", 5222);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
public void start()
{
string message = "<?xml version=1.0?><stream:streamto='gmail.com'xmlns='jabber:client'xmlns:stream='http://etherx.jabber.org/streams'version='1.0'>";
var buffer = Encoding.UTF8.GetBytes(message);
args.RemoteEndPoint = host;
args.Completed += SocketAsyncEventArgs_Completed;
args.SetBuffer(buffer, 0, buffer.Length);
bool completesAsynchronously = socket.ConnectAsync(args);
if (!completesAsynchronously)
{
SocketAsyncEventArgs_Completed(args.ConnectSocket, args);
}
}
private void SocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e)
{
if (e.SocketError != SocketError.Success)
{
Deployment.Current.Dispatcher.BeginInvoke(() => MessageBox.Show("Error during socket operation: " + e.SocketError));
return;
}
byte[] buffer = e.Buffer;
XDocument temp = ConvertByteArrayToXml(buffer);
}
XDocument ConvertByteArrayToXml(byte[] data)
{
XmlReaderSettings settings = new XmlReaderSettings();
using (MemoryStream stream = new MemoryStream(data))
using (XmlReader reader = XmlReader.Create(stream, settings))
{
return XDocument.Load(reader);
}
}
At Return XDocument.Load(reader) I get exeption '1.0' is an unexpected token. The expected token is '"' or '''. How can solve it?
Why I want it? Because when I authorize myself and change status it not affect it at my account.
Please do not write your own XMPP library from scratch, but choose one of the existing ones.
You're not going to be successful thinking of the XML you receive like a file, which is where your Unexpected end of file has occurred error is coming from. You must parse the XML incrementally.
This (in your declaration for message):
<?xml version=1.0?>
is an invalid XML declaration. As per the exception, you want:
<?xml version="1.0" ?>
Note that this has nothing to do with Jabber or sockets, and everything to do with XML. It's important to pay attention to exception messages and stack traces, so you can diagnose this sort of thing for yourself: you need to be able to isolate the area of the problem, so you can tackle just that one bit in isolation.
(The rest of that XML looks pretty bust, too, by the way.)

Categories