Home

ASP.NET: Object Serialization

 

Object Serialization and De-Serialization

 

Introduction

With file processing, we know that we can save values from a web page to the server. The values are saved individually, one at a time. When necessary, we can also retrieve the values stored in a file. This is illustrated in the following code:

<%@ Page Language="C#" %>
<%@ Import Namespace="System.IO" %>


<html>
<head>

<script runat="server">
private void btnSaveClick(object sender, EventArgs e)
{
    string Filename  = Server.MapPath("Employee.mpl");

    try {
    	FileStream fstExercise = new FileStream(Filename, FileMode.Create);
	BinaryWriter bwExercise = new BinaryWriter(fstExercise);
    
    	try {
	    bwExercise.Write(txtEmployeeNumber.Text);
    	    bwExercise.Write(txtFirstName.Text);
	    bwExercise.Write(txtLastName.Text);
    	    bwExercise.Write(txtHourlySalary.Text);

	    txtEmployeeNumber.Text = "";
	    txtFirstName.Text      = "";
    	    txtLastName.Text       = "";
	    txtHourlySalary.Text   = "0.00";
	}
    	finally {
    	    bwExercise.Close();
	    fstExercise.Close();
	}
    }
    catch(Exception)
    {
	lblMessage.Text = "There was a problem. The file cannot be saved.";
    }
}

private void btnOpenClick(object sender, EventArgs e)
{
    string Filename = Server.MapPath("Employee.mpl");
    
    if(File.Exists(Filename) == true)
    {
	FileStream fstExercise = new FileStream(Filename, FileMode.Open);
    	BinaryReader brExercise = new BinaryReader(fstExercise);

    	try
    	{
	    txtEmployeeNumber.Text = brExercise.ReadString();
	    txtFirstName.Text      = brExercise.ReadString();
    	    txtLastName.Text       = brExercise.ReadString();
	    txtHourlySalary.Text   = brExercise.ReadString();
    	}
    	finally
    	{
    	    brExercise.Close();
	    fstExercise.Close();
    	}
    }
}
</script>

<title>Exercise</title>

</head>
<body>

<h3>Employees Records</h3>

<form id="frmExercise" runat="server">
  <table>
    <tr>
      <td>Employee #:</td>
      <td>
        <asp:TextBox ID="txtEmployeeNumber" Width="120px"
                     runat="server"></asp:TextBox>
      </td>
    </tr>
    <tr>
      <td>First Name:</td>
      <td>
        <asp:TextBox ID="txtFirstName" Width="120px"
                     runat="server"></asp:TextBox>
      </td>
    </tr>
    <tr>
      <td>Last Name:</td>
      <td>
        <asp:TextBox ID="txtLastName" Width="120px"
                     runat="server"></asp:TextBox>
      </td>
    </tr>
    <tr>
      <td>Hourly Salary:</td>
      <td><asp:TextBox ID="txtHourlySalary" Width="120px"
                       runat="server"></asp:TextBox>
      </td>
    <tr>
      <td>
        <asp:Button id="btnSave"
                    OnCLick="btnSaveClick"
                    Text="Save" Width="120px"
                    runat="server"></asp:Button>
      </td>
      <td>
        <asp:Button id="btnOpen"
                    OnCLick="btnOpenClick"
                    Text="Open" Width="120px"
                    runat="server"></asp:Button>
      </td>
    </tr>
  </table>
  <table>
    <tr>
      <td>
	<asp:Label id="lblMessage" runat="server"></asp:Label>
      </td>
    </tr>
  </table>
</form>

</body>
</html>

Here is an example of using the web page:

Serialization

Instead of saving or retrieving individual values, an alternative is to create a class that holds the values and save an object of that class.

Object Serialization

Object serialization consists of saving a whole object as one instead of its individual fields. In other words, a variable declared from a class can be saved to a stream and then the saved object can be retrieved later or on another computer. The .NET Framework supports two types of object serialization: binary and SOAP.

Binary Serialization

 

Serialization

Binary serialization works by processing an object rather than streaming its individual member variables. This means that, to use it, you define an object and initialize it. This creates a "state" of the object. When you save the object, it is converted into a stream.

To perform binary serialization, there are a few steps you must follow. When creating the class whose objects would be serialized, start it with the [Serializable] attribute. Here is an example:

[Serializable]
public class Employee
{
    public string EmployeeNumber;
    public string FirstName;
    public string LastName;
    public double HourlySalary;
}

Before serializing an object, you should reference the System.Runtime.Serialization.Formatters.Binary namespace. The class responsible for binary serialization is called BinaryFormatter. This class is equipped with two constructors. The default constructor is used to simply create an object.

After declaring the variable, to actually serialize an object, call the Serialize() method of the BinaryFormatter class. The method is overloaded with two versions. One of the versions of this method uses the following syntax:

public void Serialize(Stream serializationStream, object graph);

The first argument to this method must be an object of a Stream-based class, such as a FileStream object. The second argument must be the object to serialize. This means that, before calling this method, you should have built the object.

Here is an example:

<%@ Page Language="C#" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Runtime.Serialization.Formatters.Binary" %>

<html>
<head>

<script runat="server">
[Serializable]
public class Employee
{
    public string EmployeeNumber;
    public string FirstName;
    public string LastName;
    public string HourlySalary;
}

private void btnSaveClick(object sender, EventArgs e)
{
    string Filename  = Server.MapPath("Employee3.xml");
    Employee empl = new Employee();

    try {
	empl.EmployeeNumber = txtEmployeeNumber.Text;
        empl.FirstName      = txtFirstName.Text;
    	empl.LastName       = txtLastName.Text;
    	empl.HourlySalary   = txtHourlySalary.Text;

    	FileStream fstExercise = null;

	try {
	    fstExercise = new FileStream(Filename, FileMode.Create);
	    BinaryFormatter bfExercise = new BinaryFormatter();
   	    bfExercise.Serialize(fstExercise, empl);

	    txtEmployeeNumber.Text = "";
	    txtFirstName.Text      = "";
    	    txtLastName.Text       = "";
	    txtHourlySalary.Text   = "0.00";
	}
	finally
	{
	    fstExercise.Close();
	}
    }
    catch(Exception)
    {
	lblMessage.Text = "There was a problem. The file cannot be saved.";
    }
}
</script>

<title>Exercise</title>

</head>
<body>

<h3>Employees Records</h3>

<form id="frmExercise" runat="server">
  <table>
    <tr>
      <td>Employee #:</td>
      <td>
        <asp:TextBox ID="txtEmployeeNumber" Width="120px"
                     runat="server"></asp:TextBox>
      </td>
    </tr>
    <tr>
      <td>First Name:</td>
      <td>
        <asp:TextBox ID="txtFirstName" Width="120px"
                     runat="server"></asp:TextBox>
      </td>
    </tr>
    <tr>
      <td>Last Name:</td>
      <td>
        <asp:TextBox ID="txtLastName" Width="120px"
                     runat="server"></asp:TextBox>
      </td>
    </tr>
    <tr>
      <td>Hourly Salary:</td>
      <td><asp:TextBox ID="txtHourlySalary" Width="120px"
                       runat="server"></asp:TextBox>
      </td>
    <tr>
      <td>
        <asp:Button id="btnSave"
                    OnCLick="btnSaveClick"
                    Text="Save" Width="120px"
                    runat="server"></asp:Button>
      </td>
      <td>
        <asp:Button id="btnOpen"
                    Text="Open" Width="120px"
                    runat="server"></asp:Button>
      </td>
    </tr>
  </table>
  <table>
    <tr>
      <td>
	<asp:Label id="lblMessage" runat="server"></asp:Label>
      </td>
    </tr>
  </table>
</form>

</body>
</html>
 
 
 

De-Serialization

De- serialization is the process of retrieving an object from a stream. To support this, the BinaryFormatter class is equipped with the Deserialize() method. Like Serialize(), the Deserialize() method is overloaded with two versions. One of them uses the following syntax:

public object Deserialize(Stream serializationStream);

This method takes as argument a Stream-based object, such as a FileStream variable, that indicates where the file is located. The Deserialize() method returns an Object object. As a goal, you want the Deserialize() method to produce the type of object that was saved so you can retrieve the values that the returned object holds. Because the method returns an Object value, you must cast the returned value to the type of your class.

 
 

Once the Deserialize() method has returned the desired object, you can access its values. Here is an example:

<%@ Page Language="C#" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Runtime.Serialization.Formatters.Binary" %>

<html>
<head>

<script runat="server">
[Serializable]
public class Employee
{
    public string EmployeeNumber;
    public string FirstName;
    public string LastName;
    public string HourlySalary;
}

private void btnSaveClick(object sender, EventArgs e)
{
    string Filename  = Server.MapPath("Employee3.xml");
    Employee empl = new Employee();

    try {
	empl.EmployeeNumber = txtEmployeeNumber.Text;
        empl.FirstName      = txtFirstName.Text;
    	empl.LastName       = txtLastName.Text;
    	empl.HourlySalary   = txtHourlySalary.Text;

    	FileStream fstExercise = null;

	try {
	    fstExercise = new FileStream(Filename, FileMode.Create);
	    BinaryFormatter bfExercise = new BinaryFormatter();
   	    bfExercise.Serialize(fstExercise, empl);

	    txtEmployeeNumber.Text = "";
	    txtFirstName.Text      = "";
    	    txtLastName.Text       = "";
	    txtHourlySalary.Text   = "0.00";
	}
	finally
	{
	    fstExercise.Close();
	}
    }
    catch(Exception)
    {
	lblMessage.Text = "There was a problem. The file cannot be saved.";
    }
}

private void btnOpenClick(object sender, EventArgs e)
{
    string Filename = Server.MapPath("Employee3.xml");
    
    if(File.Exists(Filename) == true)
    {
	FileStream fstExercise = null;

	try {
	    fstExercise = new FileStream(Filename, FileMode.Open);
            BinaryFormatter bfmExercise = new BinaryFormatter();
    	    Employee empl = (Employee)bfmExercise.Deserialize(fstExercise);

	    txtEmployeeNumber.Text = empl.EmployeeNumber;
	    txtFirstName.Text      = empl.FirstName;
    	    txtLastName.Text       = empl.LastName;
	    txtHourlySalary.Text   = empl.HourlySalary;
	}
	finally
	{
	    fstExercise.Close();
	}
    }
}
</script>

<title>Exercise</title>

</head>
<body>

<h3>Employees Records</h3>

<form id="frmExercise" runat="server">
  <table>
    <tr>
      <td>Employee #:</td>
      <td>
        <asp:TextBox ID="txtEmployeeNumber" Width="120px"
                     runat="server"></asp:TextBox>
      </td>
    </tr>
    <tr>
      <td>First Name:</td>
      <td>
        <asp:TextBox ID="txtFirstName" Width="120px"
                     runat="server"></asp:TextBox>
      </td>
    </tr>
    <tr>
      <td>Last Name:</td>
      <td>
        <asp:TextBox ID="txtLastName" Width="120px"
                     runat="server"></asp:TextBox>
      </td>
    </tr>
    <tr>
      <td>Hourly Salary:</td>
      <td><asp:TextBox ID="txtHourlySalary" Width="120px"
                       runat="server"></asp:TextBox>
      </td>
    <tr>
      <td>
        <asp:Button id="btnSave"
                    OnCLick="btnSaveClick"
                    Text="Save" Width="120px"
                    runat="server"></asp:Button>
      </td>
      <td>
        <asp:Button id="btnOpen"
                    OnCLick="btnOpenClick"
                    Text="Open" Width="120px"
                    runat="server"></asp:Button>
      </td>
    </tr>
  </table>
  <table>
    <tr>
      <td>
	<asp:Label id="lblMessage" runat="server"></asp:Label>
      </td>
    </tr>
  </table>
</form>

</body>
</html>

SOAP Serialization

 

Introduction

The .NET Framework supports another technique of serialization referred to as SOAP (which stands for Simple Object Access Protocol). This technique is a related to XML but, although we haven't studied XML, you don't need to know anything about it to use SOAP serialization.

Serialization With SOAP

To serialize an object using SOAP, you follow the same steps we reviewed for the binary serialization with one addition: you must add a certain reference.

When creating the class whose objects would be serialized, mark it with the [Serializable] attribute.

To support SOAP serialization, the .NET Framework provides the SoapFormatter class. This class is defined in the System.Runtime.Serialization.Formatters.Soap namespace that is part of the System.Runtime.Serialization.Formatters.Soap.dll assembly. In order to use The SoapFormatter class, you must reference this assembly. Then, you can create an object and initialize it as you see fit.

Before saving an object using SOAP serialization, create a Stream-based object that would indicate the name (and location) of the file and the type of action to perform. Then, declare a SoapFormatter variable using its default constructor. To actually save the object, call the Serialize() method of this class. This method uses the same syntax as that of the BinaryFormatter class: it takes two arguments. The first is a Stream-based object. The second is the object that needs to be serialized.

De-Serialization With SOAP

De-serialization in SOAP is performed exactly as done for the binary de-serialization. To support it, the SoapFormatter class is equipped with the Deserialize() method. This method uses the same syntax as its equivalent of the BinaryFormatter class. The approach to use it is also the same.

Details on Serialization

 

Partial Serialization

In the examples we have used so far, we were saving the whole object. You can make it possible to save only some parts of the class. When creating a class, you can specify what fields would be serialized and which ones would not be. To specify that a member cannot be saved, you can mark it with the [NonSerialized] attribute. Here is an example:

[Serializable]
public class Car
{
    public string Make;
    public string Model;

    // Because the value of a car can change,
    // there is no reason to save it
    [NonSerialized]
    public decimal Value;
    public uint Year;
    public byte Color;
}

After creating the class, you can declare a variable of it and serialize it, using either the binary or the SOAP approach. You can then retrieve the object and its values, using any of the techniques we learned earlier.

Implementing a Custom Serialized Class

To support serialization, the .NET Framework provides the ISerializable interface. You can create a class that implements this interface to customize the serialization process. Even if you plan to use this interface, the class you create must be marked with the [Serializable] attribute.

.NET Built-In Serialized Classes

The .NET Framework is filled with many classes ready for serialization. To know that a class is ready for serialization, when viewing its documentation either in the MSDN web site or in the help documentation, check that it is marked with the [SerializableAttribute].

 

 

   
 

Home Copyright © 2009-2015, FunctionX, Inc.