Steve Staple Steve Staple - 16 days ago 7
C# Question

How to Retrieve Encoded Data from DB in MVC Model and Decode it for display

I am building a Web Application using ASP.NET MVC C#.
I am encoding the data on the way in using a function:

public string Encode(string encodeMe)
{
byte[] encoded = System.Text.Encoding.UTF8.GetBytes(encodeMe);
return Convert.ToBase64String(encoded);
}


This is called in the class constructor:

public Booking(string name, string phone, string email, string date)
{
Name = Encode(name);
Phone = Encode(phone);
Email = Encode(email);
PreferredTime = DateTime.Parse(date);
}


So far so good, and the encrypted data is written to the database.

However, I want to decode that data when I read it back, using this function:

public static string Decode(string decodeMe)
{
byte[] encoded = Convert.FromBase64String(decodeMe);
return System.Text.Encoding.UTF8.GetString(encoded);
}


I have tried adding this in the Set{} statements like this:

public string Name
{
get
{
return _name;
}
set
{
_name = Decode(value);
}
}


Now what happens? The booking record is correctly encoded by the constructor in
db.Booking.Add(booking);
, but this Set{} statement is called during the execution of
db.SaveChanges();
and unencrypted data is added to the database, but previously encrypted data is correctly decoded on retrieval for Display. Attempting to decode unencrypted data causes an exception.

Answer

The problem is that your property is unbalanced: it Decodes when set-ting, but it does not Encode anywhere.

Also note that Entity Framework uses these properties just as well as you do. So EF calls the getter, which gets _name, which was set using _name = Decode(value);. The result: EF never sees the encoded value, it only exists for a split second in value.

To guarantee that data in the properties is always encoded you should keep the encoding/decoding out of the properties, and do it yourself if you need "the real data" (e.g. when displaying).

So the property becomes just:

public string Name
{
    get { return _name; }
    set { _name = value; }
}

or even

public string Name { get; set; }

In the Booking constructor you are already using Encode() before assigning to the properties.
In all other places where you need the 'actual' values you will need to use Decode(Name), etc.