Menu

Entity Framework – Model binding private properties

7 Comments

I’ve recently started looking on the asp.net forums and answering a few questions here and there which led me to this scenario of binding private properties in Entity Framework.

The basics of the problem were as follows:

  • MVC application storing data via Entity Framework into a database (lets face it, its going to be SQL Server)
  • A class held a value that had to be encrypted when saved to a database
  • The value needed to be visible when in the application.

Seems pretty simple and I ended up advising that the value should be kept encrypted all the time (in the database and in the model) and only decrypted by a helper called in the View.

However, I was interested to know if the path we started to take would work. The original design of the class had a public property with a setter that encrypted the value and a getter that decrypted the value. Now if Entity Framework was bound to this, the value would be read via the getter and so would be stored in the database in plain text. The idea then was to add a private property that used the same backing field but never encrypted or decrypted it. This would only be used by Entity Framework to save the encrypted value. This is not a great solution and I’d advise you take the other option of storing it encrypted all the time, then have a helper that the views call to decrypt when necessary. However, part of the poorer solution is quite interesting and may come in handy in other scenarios – binding private properties of a class with Entity Framework.

To make the chosen solution work, we needed to unmap the public property from Entity Framework which was achieved via the “NotMapped” Data Annotation. Then another private property was added to the class which would access the public property’s backing field without decrypting it. A code example it probably required here:

private string _topSecret;
[NotMapped]
public string TopSecret
{
  get
  {
    return Decrypt(_topSecret);
  }
  set
  {
    _topSecret = Encrypt(value);
  }
}

Where Encrypt and Decrypt could be any encryption algorithm. My proof of concept for the model binding tests just reversed the string. Not overly secret but effective for the testing.

 
[Column("TopSecret")]
private string ValueForDB
{
  get
  {
    return _topSecret;
  }
  set
  {
    _topSecret = value;
  }
}

You’ll see that the ValueForDB has the Column Data Annotation which allowed me to store the encrypted value in the database in a column with the same name as the publicly accessible property for the model.

By doing this we can use the TopSecret property of the model when writing LINQ queries against Entity Framework.

Since ValueForDB accesses the backing field directly, the value it will store/retrieve will always be the encrypted version.

TIP: If you are trying to use this slightly odd method of one property for the Application and one for DB access, generate your Controller and Views before you add the “NotMapped” Data Annotation to your public property. That way the auto generated Views will have HTML elements for the property.

The next step to slip our encrypted value into the database is telling Entity Framework how its supposed to bind against the private property ValueForDB.  We can do this by using a subclass in our model that inherits from EntityTypeConfiguration.

public class FortKnoxConfig : System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<FortKnox>
{
    public FortKnoxConfig()
    {
        Property(b => b.ValueForDB);
    }
}

Edit: I missed a bit of code out (a somewhat vital piece) on the application specific DbContext class:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // model definition is additive so other declaration will be applied on top rather than replacing this one
    modelBuilder.Configurations.Add(new FortKnox.FortKnoxConfig());

    // no harm leaving this in as EF binding is additive
    base.OnModelCreating(modelBuilder);
}

In the generated Views I added in the TopSecret member to the include property of the bind attribute. I only needed to do this for the Create and Edit views as it wasn’t included by default, due to the NotMapped attribute being on the Property when I chose to Scaffold the Controller.

public async Task<ActionResult> Create([Bind(Include="ID,TopSecret,OtherDataWeDontCareAbout")] FortKnox fortknox)

Then after that it was pretty much run and go, firstly choose to Create a new record, in the screenshot below we choose every letter of the alphabet in order.

Screenshot of the Visual Studio 2013 scaffolding layout for the Create View of our Model

The next screenshot shows the data in the database after we created it. Notice that the TopSecret column has the letters of the alphabet, but they are all reversed. This means the “encryption” (and I use that term very loosely) has been applied and the data is “secure” (I just use that term plain incorrectly).

Screenshot of the Database Viewer built into Visual Studio2013 showing the database table holding our secret in encrypted format (not really encrypted, just reversed)

Finally this screenshot shows the index view after the create was executed. Inside the application you get to see the secret without its “encryption”.

Screenshot of the Visual Studio 2013 scaffolding layout for the Index View of our Model, showing  the record we added from the earlier create

This is not an exercise in how to secure data, it’s meant to show you how to enable binding private properties in Entity Framework.  The only way the database could get the encrypted (reversed) data would be through the private property. It is a bit of a roundabout way of showing this but it was a real world question. Also, I believe the person who asked the question is using a much better encryption algorithm than mine, something that actually encrypts.

The code for the whole project is available on github.

Tags:

7 thoughts on “Entity Framework – Model binding private properties”

  1. James Phelps says:

    That was an interesting post. It works great know. Thanks.

  2. Damien says:

    Nice post. Thanks

    greetings Damien

  3. ivorystackhouse says:

    I love it when people come together and share views.
    Great site, stick with it!

  4. chongemery says:

    I enjoy what you guys tend to be up too. This sort of clever work and reporting!
    Keep up the fantastic works guys I’ve included you guys to blogroll.

  5. James Boxer says:

    Will love to learn more from you in the future, keep the great things coming.

  6. LowTide says:

    You had stated “By doing this we can use the TopSecret property of the model when writing LINQ queries against Entity Framework.”

    In your code, instead of doing:
    FortKnox fortknox = await db.FortKnoxes.FindAsync(id);
    and instead do something like:
    FortKnox fortknox = db.FortKnoxes.FirstOrDefault(u => u.TopSecret == “97531”);

    You will get the error: “The specified type member ‘TopSecret’ is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.”

    How can you do Linq queries on the column TopSecret?

    1. Yes I get that too, so my statement saying you can use the column in LINQ queries was wrong (sorry). I would advise you don’t actually use the technique unless you have no other option (which I doubt would ever occur) as it was just an exercise in seeing if it was possible. I’ve never actually seen a real world problem that needed this to be used. If you do have a problem where you think you need to do it, reply back to me and I’ll see if I can’t think of a better way to get past it.

Comments are closed.