Tuesday, June 30, 2009

How to serialize / deserialize ANY object using XmlSerializer

There is a lot to say about object serialization. I just want to cover the gray area when you need to serialize object which has references to other objects, but references are not strongly typed. For example, if you have your classes structured like that:

    public class MainClass


    {


        public object Data { get; set; }


    }


    public class ChildClass1


    {


        //some properties


    }


    public class ChildClass2


    {


        //some properties


    }


 


where Child Classes can be assigned to Data property of the MainClass and if you construct XmlSerializer object like this


new XmlSerializer(typeof(MainClass));


Then both serialization and deserialization will fail throwing an error saying that it has no knowledge of ChildClass1 or ChildClass2 classes. To resolve this error you need to provide XmlSerializer with additional class types which serializer may meet on its way when parsing XML string. Here is how to do that:


new XmlSerializer(typeof(MainClass), new Type[] { typeof(ChildClass1), typeof(ChildClass2) });


Here is the set of functions I use to serialize / deserialize my objects:


        public static string SerializeToString(object aObject)


        {


            return SerializeToString(aObject, null);


        }


 


        public static string SerializeToString(object aObject, Type[] extraTypes)


        {


 


            XmlSerializer aSerializer;


            if (extraTypes == null)


                aSerializer = new XmlSerializer(aObject.GetType());


            else


                aSerializer = new XmlSerializer(aObject.GetType(), extraTypes);


            MemoryStream aMemoryStream = new MemoryStream();


            StreamReader aStreamReader = new StreamReader(aMemoryStream);


 


            XmlWriterSettings aXMLWriterSettings = new XmlWriterSettings();


            aXMLWriterSettings.Encoding = new UTF8Encoding(false);


            aXMLWriterSettings.ConformanceLevel = ConformanceLevel.Document;


            XmlWriter aXMLWriter = XmlWriter.Create(aMemoryStream, aXMLWriterSettings);


 


            aSerializer.Serialize(aXMLWriter, aObject);


            aXMLWriter.Flush();


            aXMLWriter.Close();


            aMemoryStream.Position = 0;


            return aStreamReader.ReadToEnd();


        }


 


 


        public static object DeserializeFromString(string aMessage, System.Type aType)


        {


            return DeserializeFromString(aMessage, aType, null);


        }


 


        public static object DeserializeFromString(string aMessage, System.Type aType, Type[] extraTypes)


        {


            XmlSerializer aXMLSerializer;


            if (extraTypes == null)


                aXMLSerializer = new XmlSerializer(aType);


            else


                aXMLSerializer = new XmlSerializer(aType, extraTypes);


            System.IO.StringReader aStringReader = new StringReader(aMessage);


 


            return aXMLSerializer.Deserialize(aStringReader);


        }


 


-= Oleg =-

Thursday, June 25, 2009

My experiences with LINQ (basic use with C#)

So here's how it started:

"Fill an object that consists of lists of other objects that consist of lists of other objects from the database"

Meaning, I have to retrieve data from 4-5 different tables, efficiently and bring it in to my app. My first idea: Iterate through the object and write separate queries that will populate each list, and than iterate through each object in the list and fill that one in turn. The number of transactions would be huge... so not such a great idea. Finally I came to the conclusion that an XML record set
 (SELECT
                itemType AS '@type',
                Id AS 'Id'
FROM MyDataTable WHERE Id = @Id
FOR XML PATH('Item'), TYPE)

with a few of those nested, would be a more sensible approach.

After spending a day linking my tables and selecting which values I need and which are junk, I started with the XML parsing. Of course this can be done in many ways, ranging from straight parsing with XPathNavigator to serialization straight into the object, or even transforming the XML using an XSL transform and than serializing it into an object. All those are fun approaches, but this time I decided that I'll use that handy little tool that Microsoft has: LINQ.

Language-integrated Query they call it. Mainly it's used for writing XML files, and unfortunately most examples are regarding that. Of course, as with anything new that I do, I browsed the net for some examples, and gave up after about 5 minutes, and just started fiddling around with it... Here are my discoveries:

The basic statement to use is:
var vComponents = from item in sampleXML.Descendants("component")
     select item;

this gives you a list of items which you can iterate through with something like:
foreach (var vComponent in vComponents)

you may notice that this is a generic type (var) which is a LINQ free-form variable. In this case vComponents is a System.Linq.Enumerable and the vComponent is an XML container (the inner workings of LINQ are not my main concern).

To extract a value from the XML container you might want to use something like:
int myValue = int.Parse(vComponent.Element("myValue").Value);
Guid myGuid = new Guid(vComponent.Attribute("id").Value);

which is pretty straight forward. The fun thing is that you can than take your node vComponent, and use it as you would with any other XML document, so you can say something like:
var vElements = from item in vComponent.Descendants("Element")
select item;

or even:
string itemName = vElements.Element("ItemInfo").Element("ItemName").Value;

Of course, doing stuff like this with XML is risky, because let's say one of your JOINS from the database yielded some NULL values, so you might want to first check for the element to not be NULL before you query for the value, like:
if (vElements.Element("ItemInfo").Element("ItemDescription") != null)
itemDescription = vElements.Element("ItemInfo").Element("ItemDescription").
Value;

just in case the description field was left NULL.

Of course, you might want to wrap it all up in some try{ ... } catch { ... } statements just to prevent any other nasty errors from popping up.

In conclusion, I guess all I can say is: "XML parsing made easy" using Linq. It's good for iterating through multiple nodes of the same type, but I'd expect some nicer way for it to handle errors (like if a node is non existant, don't throw an error just return a NULL value, like serialization does). Hopefully I'll find some time and write a bit about serialization as well...

alex~

Thursday, June 18, 2009

Deploying Silverlight - revisited

An error of the type:

Parser Error Message: Could not load file or assembly 'System.Web.Silverlight' or one of its dependencies. The system cannot find the file specified.


...


<%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls" TagPrefix="asp" %>



Caused by embedding your application on an .aspx page, can be solved in Visual Studio by simply going to the project containing your page, and for the System.Web.Silverlight reference, change "Copy Local = True". After doing this don't forget to copy the .dll file together with your .aspx page.

alex~

How to deploy Silverlight application to a Server

In two words: 1) copy your *.xap files; 2) make sure .xap and .xaml MIME types are registered.

Here is more information about registering mime types for Silverlight application.

Warning, if you are deploying your Silverlight application to a Virtual Folder of the existing website, then most likely you need to copy your ClientBin folder to the root of the website, not virtual folder.

-=Oleg=-

Wednesday, June 17, 2009

Silverlight Password Textbox

Silverlight Textbox is not the same as ASP.NET.  There is no TextMode property that can be set to "password".

Silverlight has a special control for Password fields. It's called PasswordBox

Here is the sample of XAML with PasswordBox:
<PasswordBox Password="HelloWorld" x:Name="pbPassword">

 Another surprise from Silverlight development team is that PasswordBox control doesn't have Text property. In order to retrieve the value of the Password field use the Password property instead:
string sPassword  = tbPassword.Password;

Recently I had to work on a prototype where TextBox control was originally used for collecting password information. So, I went and replaced TextBox control with Password control and then changing Text property to Password. Guess what, my code compiled fine but when I tried to run it, it crashed. The reason was in Style property.
<PasswordBox Password="HelloWorld" x:Name="pbPassword"
Style="{StaticResource myTextBoxStyle}" >

This style was defined for the TextBox. This style is not compatible with PasswordBox control. I didn't have a chance to look at what exactly in myTextBoxStyle style is causing problems. I will find it out and update this post.

One more note about PasswordBox is that it has PasswordChar property which can be used to specify the masking character. It's a nice useless feature with no real value. It would be much nicer if PasswordBox was inherited from TextBox so developers won't spend their valuable time building special cases around this control.

Oleg.

Silverlight 3 Beta - My first bug

At first, our encounter with the Silverlight 3 Beta was a good experience. Nice backward compatibility with code compiled in Silverlight 2, and without a re-compile it supported some new Video formats out of the box (that Silverlight 2 didn't support).

Unfortunately, a day or two after, something really broke down, and now my Internet Explorer will not run Silverlight and Flash in the same window without crashing my app. Currently we have this issue on the Silverlight.net site:

http://silverlight.net/forums/t/101974.aspx

Hopefully someone will take a look at it.

alex~

About us

Out of space we came with ... a smile.

alex_75 and oleg_75