Tag Archives: serialization

Passing a small object in the querystring

For the current project at work I need to pass some information from an application or website to another website. Rather than storing the state in a database I decided to serialize the state object and pass it, encrypted, in the querystring.

This is the encoding function:

Dim plaintext as String = myState.Serialize
Dim bytes As Byte() = ASCIIEncoding.UTF8.GetBytes(plaintext)
Dim encrypted As Byte() = Encryption.Encrypt(bytes, key)
Dim encodedtext As String = Convert.ToBase64String(encrypted)
Return System.Web.HttpUtility.UrlEncode(encodedtext)

Note that the serialized and encrypted object is url encoded using the System.Web.HttpUtility.

This is the decode function:

Dim decodedtext As Byte() = Convert.FromBase64String(querystring)
Dim decrypted As Byte() = Encryption.Decrypt(decodedtext, key)
Dim plaintext As String = ASCIIEncoding.UTF8.GetString(decrypted)
Dim mystate As New State
Return mystate

and in C# because I need to practice my skills:

byte[] decodedtext = Convert.FromBase64String(querystring);
byte[] decrypted = Encryption.Decrypt(decodedtext, key);
string plaintext = ASCIIEncoding.UTF8.GetString(decrypted);
State mystate = new State();
return mystate;

Note that the querystring is not url decoded, this is because the ASP.NET http handler decodes the querystring before it is passed to your code.

Self Serializing Base Class

This class can be used as a base for any class that needs to serialize and deserialize itself.

Imports System.Xml.Serialization
Imports System.Xml
Imports System.IO
''' <summary>
''' Base class for any object that can serialize itself either normally or cleanly. i.e. without the xml declaration thus making it useful for insertion into other xml.
''' </summary>
''' <remarks>Note that self deserialization is not possible</remarks>
Public MustInherit Class SelfSerializer
''' <summary>
''' This class can serialize itself with namespace and xml declaration.
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
<System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")>
Public Function Serialize() As String
Dim serializer As New XmlSerializer(Me.GetType)
'Need to serialize without namespaces to keep it clean and tidy
Dim emptyNS As New XmlSerializerNamespaces({XmlQualifiedName.Empty})
Using stream As New StringWriter(), writer As XmlWriter = XmlWriter.Create(stream)
'Serialize the item to the stream using the namespace supplied
serializer.Serialize(writer, Me)
'Read the stream and return it as a string
Return stream.ToString
End Using
End Function
''' <summary>
''' This class can serialize itself without namespace or xml declaration.
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
<System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")>
Public Function SerializeAsElement() As String
Dim serializer As New XmlSerializer(Me.GetType)
'Need to serialize without namespaces to keep it clean and tidy
Dim emptyNS As New XmlSerializerNamespaces({XmlQualifiedName.Empty})
'Need to remove xml declaration as we will use this as part of a larger xml file
Dim settings As New XmlWriterSettings()
settings.OmitXmlDeclaration = True
settings.NewLineHandling = NewLineHandling.Entitize
settings.Indent = True
settings.IndentChars = (ControlChars.Tab)
Using stream As New StringWriter(), writer As XmlWriter = XmlWriter.Create(stream, settings)
'Serialize the item to the stream using the namespace supplied
serializer.Serialize(writer, Me, emptyNS)
'Read the stream and return it as a string
Return stream.ToString
End Using
End Function

#Region "Self deserialization"

Private myState As Object = Me
''' <summary>
''' Deserialize
''' </summary>
''' <param name="xml"></param>
''' <remarks>This is a shallow copy so won't read any nested objects.</remarks>
Public Sub Deserialize(xml As String)
Dim newMe As Object 'We don't know our own type so we have to use an object here
'Read text
Dim newSerializer As New XmlSerializer(Me.GetType)
Using newReader As New StringReader(xml)
newMe = newSerializer.Deserialize(newReader)
myState = newMe
End Using
For Each propinfo In myState.GetType.GetProperties()
Dim name = propinfo.Name
Dim realProp = (From p In Me.GetType.GetProperties
Where p.Name = name And p.MemberType = Reflection.MemberTypes.Property).Take(1)(0)
realProp.SetValue(Me, propinfo.GetValue(myState, Nothing), Nothing)
End Sub

#End Region
End Class

Include a namespace prefix when serializing or deserializing

In order to include a namespace prefix when serializing a class we must add an xmlns property of type XmlNamespaceDeclaration to the class and then add a prefix in the class constructor.

Imports System.Xml.Serialization

    <Serializable(), XmlRoot("navigation", Namespace:="<a href="http://www.tla.com/">http://www.tla.com</a>")>
    Public Class Navigation
        ''' <summary>
        ''' Add a namespace declaration so that we can use a prefix for this class.
        ''' </summary>
        ''' <remarks>
        ''' See <a href="http://msdn.microsoft.com/en-us/library/vstudio/system.xml.serialization.xmlnamespacedeclarationsattribute(v=vs.90).aspx">http://msdn.microsoft.com/en-us/library/vstudio/system.xml.serialization.xmlnamespacedeclarationsattribute(v=vs.90).aspx</a>
        ''' and <a href="http://stackoverflow.com/questions/1254544/how-do-i-specify-xml-serialization-attributes-to-support-namespace-prefixes-duri">http://stackoverflow.com/questions/1254544/how-do-i-specify-xml-serialization-attributes-to-support-namespace-prefixes-duri</a> </remarks>
        <XmlNamespaceDeclarations> Public xmlns As New XmlSerializerNamespaces

        Public Sub New()
            'Add thenamespace prefix
            xmlns.Add("tla", "<a href="http://www.tla.com/">http://www.tla.com</a>")
        End Sub

    End Class

    Public Class Heading

        Public Sub New()
   'Default constructor
        End Sub

        Private myQuestions As List(Of Question)
        ''' <summary>
        ''' Flat sequence of questions.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks>Using the XmlElementAttribute markup renders the list as a flat sequence.</remarks>
        <XmlElementAttribute("question", GetType(Question))>
        Public Property Questions() As List(Of Question)
                If myQuestions Is Nothing Then myQuestions = New List(Of Question) 'Lazy loading
                Return Me.myQuestions
            End Get
            Set(value As List(Of Question))
                Me.myQuestions = value
            End Set
        End Property
    End Class

    Public Class Question
        <XmlAttribute()> Public Property id() As String
    End Class