Blog
what did i learn today
Uncategorized csharp xml
Easy XML reading using XmlTextReader

When looking at examples and samples for the .NET System.Xml.XmlTextReader, i was hoping it would be as easy to use as XmlTextWriter. But i did not find such examples.

XmlTextReader will read node per node, using the method Read, and a programmer will have to evaluate what type of node the current node is. But XmlTextReader has two short-hand methods: ReadStartElement and ReadElementString.

Suppose we have the following xml :

 <root>
   <itemlist>
     <item> 
       <name>Item1</name> 
       <value>110</value>
     </item>
     <item>
       <name>Item2</name>
       <value>234</value>
     </item>
     <item>
       <name>Another Item</name>
       <value>432</value> 
     </item> 
   </itemlist>
 </root>

What we want to do is read one item in a simple way. That is possible as follows:

 private void ReadItem(XmlTextReader reader, out String name, out String value) { reader.ReadStartElement("item"); name = reader.ReadElementString("name") ; value = reader.ReadElementString("value"); reader.ReadEndElement(); //item } 

Unfortunately ReadStartElement will throw an exception if the current element is not the same as the wanted element. So we need a bit more code to iterate smartly over all possibilities.

private void ReadItemList(XmlTextReader reader) 
{ 
    reader.ReadStartElement("itemlist"); 
    reader.Read(); 
    // read next element 
    while (reader.LocalName == "item") 
    { 
        String name; 
        String value; 
        ReadItem(reader, out name, out value) ; 
        // ... do something here with read item ... 
        reader.Read(); 
    } 
    reader.ReadEndElement(); // itemlist 
}

The reader.Read() positions ourself on the next node, allowing some kind of look-ahead, while the ReadEndElement and ReadStartElement can handle this perfectly well. They will either proceed to the next node, or stay on the current node. That's why this code works. For completeness, this does the setup:

XmlTextReader importReader = new XmlTextReader(fileName); 
importReader.ReadStartElement("root"); 
ReadItemList(importReader); 
importReader.ReadEndElement(); 

... where filename points to the file containing the above shown xml.

If you have any questions or comments regarding this example, please let me know.

This allows for very readable and concise code, but only if you know how the xml file you are reading is formed (the order of the elements). I will solve this in the next post.

More ...
Uncategorized wcf csharp
WCF maximum string length

WCF and MaxStringContentLength on XmlDictionaryReaderQuotas

When sending xml-data over WCF using a string, i bumped into the following error :

The formatter threw an exception while trying to deserialize the message: Error in deserializing body of 
request message for operation 'Test'. The maximum string content length quota (8192) has been exceeded 
while reading XML data. This quota may be increased by changing the MaxStringContentLength property 
on the XmlDictionaryReaderQuotas object used when creating the XML reader.

Right. This sounded like some foreign language where i can't even make out the syllables. I am using WCF with a NetTcpBinding, so after extensive googling i was able to produce the following C# code :

    ushort myport= 27001;
    const Int32 myMaxMessageSize = 6553500;
    string address = String.Format("net.tcp://localhost:9000/myservice/{0}", myport);
    XmlDictionaryReaderQuotas quotas = new XmlDictionaryReaderQuotas();
    quotas.MaxStringContentLength = myMaxMessageSize;

    NetTcpBinding binding = new NetTcpBinding();
    binding.ReaderQuotas = quotas;
    binding.MaxReceivedMessageSize = myMaxMessageSize;
    binding.MaxBufferSize = myMaxMessageSize;

    m_factory = new ChannelFactory<imyservicecontract>(binding);

    m_proxy = m_factory.CreateChannel(new EndpointAddress(address));

Setting the MaxStringContentLength alone doesn't cut it. Once your buffer grows larger than 65K (the default for MaxBufferSize and MaxReceivedMessageSize ) you will run into errors again. So that's why i opted to change those as well.

Hope this helps :)

More ...