December 1, 2009

How can I customize my user model in my ASP.NET MVC web site? Part 1

Introduction

Related Posts

Well it's about time I wrote another blog post so I thought I'd cover some material that's caused me a lot of headaches and frustrations this week: Trying to integrate ASP.NET's web security and profile models into an MVC application that I'm jointly developing with @JohnMacIntyre.

Because of the amount of material, I will spread it over a number of posts to attempt to keep things succinct and easy to read. I trawled through many blogs in order to try and gleen useful information, but in the end most of it was futile and I ended up getting most of my understanding from Timothy VanFosson via StackOverflow.com (Thanks Tim, I appreciate it) and right from the .NET Framework courtesy of Red Gate's .NET Reflector - Thank you Red Gate :)

I have made some assumptions about you, the reader and I apologize now if any of them are wrong.

  1. You already have Visual Studio 2008 installed and are running .NET Framework 3.5.
  2. You have ASP.NET MVC 1.0 downloaded and installed.
  3. You’ve created a new ASP.NET MVC Project.
  4. You already understand the concepts of the MVC model – I won’t be discussing them as that’s beyond the scope of this post/tutorial.
  5. You’ve already looked at the out of the box database generated by aspnet_regsql and decided that’s not going to work for your site and like me you’re frustrated at the lack of serious documentation about how to use the existing .NET Membership/Role/Profile Framework on top of your own model.
  6. You already understand the Provider Pattern - It will make life easier if you have read and at least understand the provider model to a rudimentary level. If you haven’t, then the following documents are good reading that will help you understand it [the PDF is probably the most comprehensive, but it’s 136 pages]
    1. ASP.NET 2.0 Provider Model: Introduction to the Provider Model
    2. The ASP.NET 2.0 Provider Model [PDF]
    3. The .NET 2.0 Framework Provider Pattern

It would seem from many blog posts out there that most people seem to be using the aspnet_regsql wizard and using out-of-the-box functionality provided by Microsoft. This process appears to be fairly well done to death, so I won’t continue to beat a dead horse. Instead, I will be taking a different approach – one that allows us to take complete control of our database schema and throw out the schema and procedures that the default model uses.

This caused me no end of frustration because we'd already designed our database model and I'm not happy to rip it out and start again just because that is the way all the material I can find tells me I should do it. So I will provide a step by step tutorial of the understanding I've gleened along the way and hopefully where I've misunderstood others may provide further insight and/or correction.

So let’s mock up a database schema that we’ll be working to. This is just a quick knock together for demonstration purposes, so no best practice bashing please. And while this schema is probably a lot different than the schema you wish to use for your system the techniques I will discuss should be easily transferrable.

Create Table Roles(
 RoleId Int Identity(1, 1) Not Null
 RoleName NVarChar(64),
 Constraint PK_Roles Primary Key Clustered(
  RoleId Asc
 )
)
Create NonClustered Index IX_Roles_RoleName On Roles(
 RoleName Asc
)

Create Table Users(
 UserId Int Identity(1,1) Not Null,
 FirstName NVarChar(32), 
 LastName NVarChar(32) Not Null,
 UserName NVarChar(104) Not Null,
 DisplayName NVarChar(32),
 EmailAddress NVarChar(254) Not Null,
 Password NVarChar(256) Not Null,
 Question NVarChar(64) Not Null,
 Answer NVarChar(64) Not Null,
 CreateDate DateTime Not Null,
 LastLoginDate DateTime,
 LastActivityDate DateTime Not Null,
 LastUpdateDate DateTime Not Null,
 Location NVarChar(64),
 Biography NText,
 Constraint PK_Users Primary Key Clustered(
  UserId
 )
)
Create NonClustered Index IX_Users_UserName On Users(
 UserName Asc
)

UserRoles(
 UserId Int Not Null Constraint FK_UserRoles_UserId Foreign Key
 RoleId Int Not Null Constraint FK_UserRoles_RoleId Foreign Key
 Constraint PK_UserRoles Primary Key Clustered(
  UserId,
  RoleId
 )
)
Create NonClustered Index IX_UserRoles_UserId On UserRoles(
 UserId Asc
)
Create NonClustered Index IX_UserRoles_RoleId On UserRoles(
 RoleId Asc
)

Okay, that should suffice for the purpose of a prototype. I considered role inheritance schema (i.e. roles that inherit other roles), but considered them unnecessary for the scope of these posts. Maybe in a future post I will revisit that, but for now, we’ll stick with this model. In further posts on this topic, I will be referring to this schema, so print it out and pin it up next to your monitor ;)

No comments:

Post a Comment