I have a simple class I am designing to log messages on a hosted website.
To store the messages, I have created this simple class structure:
public class StoredMsg {
public StoredMsg() {
}
public string From { get; set; }
public string Date { get; set; }
public string Message { get; set; }
}
These messages will be written and read back using a StoredMessages : List<StoredMsg>
class.
This is the original format of the Read
method:
public void Read() {
//string xmlPath = WebPage.Server.MapPath(XML_PATH);
if (File.Exists(xmlPath)) {
using (var xr = new XmlTextReader(xmlPath)) {
StoredMsg item = null;
while (xr.Read()) {
if (xr.NodeType == XmlNodeType.Element) {
if (xr.Name == HEAD) {
if (item != null) {
this.Add(item);
}
item = new StoredMsg();
} else if (xr.Name == FROM) {
item.From = xr.ReadElementString();
} else if (xr.Name == DATE) {
item.Date = xr.ReadElementString();
} else if (xr.Name == MESSAGE) {
item.Message = xr.ReadElementString();
}
}
}
xr.Close();
}
}
}
The Write
method was originally in this format:
public void Write(StoredMsg item) {
using (var stream = File.Open(xmlPath, FileMode.Append, FileAccess.Write, FileShare.Read)) {
using (var xw = new System.Xml.XmlTextWriter(stream, Encoding.UTF8)) {
xw.WriteStartElement(HEAD);
{
xw.WriteWhitespace("\r\n\t");
xw.WriteElementString(FROM, item.From);
xw.WriteWhitespace("\r\n\t");
xw.WriteElementString(DATE, item.Date);
xw.WriteWhitespace("\r\n\t");
xw.WriteElementString(MESSAGE, item.Message);
xw.WriteWhitespace("\r\n");
}
xw.WriteEndElement();
xw.WriteWhitespace("\r\n");
}
stream.Close();
}
}
The problem was that the Read
method did not like something in the structure of my XML, so my list was always empty.
It is hard to troubleshoot this on a hosted website, so I started looking online at examples to see what I might have been doing wrong.
During my search, I found Microsoft's How to: Write Object Data to an XML File (C# and Visual Basic) which showed me a simple way to streamline what my Write
method had done:
private XmlSerializer serializer;
public StoredMessages() {
serializer = new XmlSerializer(typeof(StoredMsg));
}
public void Write(StoredMsg item) {
using (var file = new StreamWriter(xmlPath, true)) {
serializer.Serialize(file, item);
}
}
That, to me, is simplicity and elegance!
Being happy with this, I went on to Microsoft's How to: Read Object Data from an XML File (C# and Visual Basic), so I could implement it as well.
Here is the problem:
The best I can seem to do is write my method like this:
public void Read() {
if (File.Exists(xmlPath)) {
using (var file = new StreamReader(xmlPath)) {
// How do I handle multiple nodes?
// http://msdn.microsoft.com/en-us/library/vstudio/ms172872.aspx
var item = (StoredMsg)serializer.Deserialize(file);
this.Add(item);
}
}
}
I am very interested in seeing someone show me how to read all of my items in Linq to XML and I will give a +1 for that, but the question here is how I would read all of my data in using this Read
technique above.
Is it that I am incorrectly casting the deserialized object to a StoredMsg
instead of something else? If so, what would the something else be?
StoredMsg[]
?List<object>
?StoredMessages
?
Thanks for reading all of this, and I hope my code is legible to others.
Example data provided as a screenshot to prevent others from grabbing my email address too easily: