Wednesday, December 11, 2013

Note to self - how to do many to many in Entity Framework code-first

I've probably done a handful of EF code-first projects and I always forget how to do the mappings. I always end up looking at old projects and try to figure out what went on. This is a good place to make notes. In my last project I had no idea what I was looking at. Old age has crept up.

I won't go over the whole DbContext Model classes thing,  but in case someone is reading this that isn't familiar, you make a your model classes for your application and they become mapped to your database entities in the Entity Framework ORM world.

So, for example say we have these two model classes amongst our many other model classes:
  • WatchingList
  • Thing


We would then create our DbContext class by creating a class and implementing from DbContext class. For example:

public class MyProjectDbContext : DbContext
{
   // in here we will map our model objects with DbSet<>
   public DbSet<WatchingList> WatchingLists { get; set;}
   public DbSet<Thing> Things { get; set;}

     ... and so on...
}

The above is where all the magic happens. Look elsewhere for a fuller explanation, but in short when we run our app after having done the above, we can then use LINQ to query the database objects, the database will be created for us if it doesn't already exist.

On another note, if it does already exist then we can configure our project to recreate the database on changes. I'm not going to write about that but it's great do developing though probably not great for production systems :)

Many to Many mapping

Anyway, to do the many to many mappings we'll need a

modelBuilder.Entity<WatchingList>()
      .HasMany((w => w.Things).WithMany()
      .Map(m => m.ToTable("WatchingList_Thing")
      .MapRightKey("ThingId")
      .MapLeftKey("WatchingListId"));

Basically,  ThingId and WatchingListId are the columns in the mapping table and the mapping table will be called  WatchingList_Thing

Abstract base classes

If we have some inheritance with these three model objects say,

  • Animal - maybe an abstract base class for the other two concrete classes listed here
  • Dog - inherits/extends the Animal class
  • Cat - inherits/extends the Animal class
If we have these three model classes declared with DbSet in the usual way we will get three tables with those names. We might want to have the table names in the database slightly different to reflect their relationship. We can do that by also overriding the OnModelCreating() method.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
   modelBuilder.Entity<Animal>().ToTable("Animal");
   modelBuilder.Entity<Dog>().ToTable("Animal_Dog");
   modelBuilder.Entity<Cat>().ToTable("Animal_Cat");
}
So we've controlled the naming of tables by EF.






Tuesday, December 10, 2013

XSRF Cross Site Request Forgery attack - ASP.NET MVC

This is a note on the topic that I've been meaning to write for a very long time. I'm a bit old, been around a bit and have worked with a whole range of people. The interesting thing about the XSRF is that I hardly hear it mentioned in the work place. I hope other folk have a better experience. But we just seem to be getting on with the list of functional requirements in time for the next deadline. Perhaps that why it's not talked about enough but it is probably the most 'popular' security vector being exploited by the nasty people.

A quick intro.

In simple terms:

  1. A friendly person A visits our happy site Happy.com and logs in. 
  2. Happy.com site authenticates him and gives him a cookie so that every time he visits us we know he's a good guy.
  3. Unknowingly, friendly guy A visits a bad site Evil.com.
  4. Evil site Evil.com will sneakily return a malicious form tag that will request to our Happy.com site. This malicious code will be allowed to access our server because it is attached to the authentication cookie we gave him and we think that it has already been authenticated.
  5. Bad things can happen.

This works because the authentication cookie is being transported with the request. 
The only way to prevent this is to ensure the form is created by the good user. We use an antiForgery token to help here. 


In the View we put the anti forgery helper:

<% using (Html.BeginForm()) {%>
    <% = Html.AntiForgeryToken() %>


In the controller action we use the ValidateAntiForgeryToken attribute:

[ValidateAntiForgeryToken]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, 

With this asp.net creates a crypto token that can't be created by the Evil user.