ASP.NET Registration with multiple profile providers

by andrew 8/23/2007 5:07:04 AM
Building a custom registration page

using the CreateUserWizard control is a 5 minute task in ASP.NET 2. However what happens if you want to do things slightly differently? You want to use the Email address as the Username, and you also want to store common fields such as Firstname and Lastname in standard tables (rather than have them encrypted in aspnet_profile). The solution is easy but not immediately obvious (not to me anyway). First of all lets walk through a common scenario.

A fairly typical registration form would contain the following fields :-

  • Email Address (which is also the username)
  • Password
  • First Name
  • Last Name
  • Hair Colour*

By default the create user wizard codelessly manages Username, Email, Password, Secret Question/Answer straight out of the box. Sadly, by configuration alone, you cannot change the Wizard to use Email Address as the Username, nor will it recognise Firstname or Lastname. To my mind, these 2 options are so common that Microsoft should have built the functionality straight in.

Thankfully, the solution is still pretty easy - with the use of the ASP.NET Profile System and the profile model. First to support the extra fields: adding the below to the Web.Config file is all that is needed to configure the website's profile system to allow the storage of Firstname, Lastname and HairColour.

<profile defaultProvider="SqlProvider">
<providers>
<clear />
<
add name="SqlProvider" type="System.Web.Profile.SqlProfileProvider"
connectionStringName="SqlServices"
applicationName="MyApplication"
description="SqlProfileProvider"/>
</providers>
<properties>
<add name="Firstname" type="string"/>
<add name="Lastname" type="string"/>
<add name="HairColour" type="string"/>
</properties>
</profile>

Now add the FirstName, LastName and HairColour labels and input boxes to the CreateUserWizard template, and then code the following event handler.

protected void CreateUserWizard1_CreatedUser(object sender, EventArgs e)
{
ProfileCommon p = (ProfileCommon)ProfileCommon.Create(CreateUserWizard1.UserName, true);
p.Firstname = ((TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("Firstname")).Text;
p.Lastname = ((TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("Lastname")).Text;
p.HairColour = ((TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("Haircolour")).Text;
p.Save();
}

This is all that is required to save the new fields to the profile data store, which in this case is SQL Server. So far this all seems fine, until we look at the Profile data model.

The aspnet_Profile stores the data in a pretty weird fashion.

Field Name Values
PropertyNames FirstName:S:0:6:LastName:S:7:6:
PropertyValuesString Andrew Rimmer

Basically the field value pairs get stored in a way that is easy to extract programmatically but is difficult to query via database queries alone. You can understand why it was done this way, it is completley extensible, and the database schema is fixed. If Marketing decide they want to capture eye colour too, its a quick change to the Wizard HTML and the Web.Config - No database changes required. I believe this is fine for HairColour and EyeColour, and other such questions but what about FirstName and Lastname. For any system of size I would never consider storing this data in such a retarded way. Thankfully some clever guys have come up with alternative providers to get around this problem.

Meet the SqlTableProfileProvider and the SqlStoredProcedureProfileProvider. These 2 providers have been developer by Hao Kung - a software engineer at Microsoft. They are pretty simple and effective.

Basically the SqlTableProfileProvider allows you to map Profile properties to database columns, whilst the SqlStoredProcedureProfileProvider allows you to map Profile properties to Stored Procedure parameters. This means that you can store Profile properties anywhere within your data model - in clear fields. I think for Firstname and Lastname this is a must, and possibly for quite alot of other fields depending on your circumstances.

The beauty of the Provider model really shines when it comes to integrating this new functionality. The only changes that are required are the inclusion of the providers into the project, and then an update to the Web.Config. BOOM! But is there a snag? Have we compromised by changing our Profile Provider. If we start adding new fields to the Registration form, will we have to extend our database schema? The answer is No, or more accurately the answer is 'it is up to you'. You see, the Profile provider model allows you to choose which provider to use for which field. This allows you granular control over how your profile is to be stored.

For my example above, I would definintely want to store Firstname and Lastname as clear fields in my database, but I wouldn't be bothered about storing Haircolour in the clear, as this isn't a core business field.

So we need to configure the Profile system to use multiple profile providers, and this is how to do it.

First create a table to store the Firstname and Lastname.

CREATE TABLE [dbo].[UserProfile](
[UserID] [uniqueidentifier] NOT NULL,
[Firstname] [varchar](50) NULL,
[Lastname] [varchar](50) NULL,
[LastUpdatedDate] [datetime] NULL,
CONSTRAINT [PK_UserProfile] PRIMARY KEY CLUSTERED
( [UserID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

Now update the configuration...

<profile defaultProvider="SqlProvider">
<providers>
<clear />
<add name="SqlProvider"
type
="System.Web.Profile.SqlProfileProvider"
connectionStringName
="SqlServices"
applicationName
="MyApplication"
description
="SqlProfileProvider" />
<add name="TableProfileProvider"
type
="Microsoft.Samples.SqlTableProfileProvider"
connectionStringName
="SqlServices"
table
="UserProfile"
applicationName
="MyApplication"/>
</
providers>
<properties>
<
add name="Firstname" defaultValue="[null]"
customProviderData
="Firstname;varchar"
provider="TableProfileProvider"/>
<add name="Lastname" defaultValue="[null]"
customProviderData="Lastname;varchar"
provider="TableProfileProvider"/>
<add name="HairColour" type="string"/>
</properties>
</profile>

 


And that is it. We now store important fields where they belong - in normal database fields, whilst retaining the extensibility of the Profile system by allowing non-essential fields to be munged into the aspnet_profile table.

Currently rated 3.8 by 4 people

  • Currently 3.75/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Comments

9/21/2007 8:44:44 AM

sohbet

thanks baby

sohbet

10/23/2007 6:49:56 PM

sohbet

thanks a lot..

sohbet tr

Add comment


(Will show your Gravatar icon)  

  Country flag





Live preview

8/20/2008 4:04:43 PM

Powered by BlogEngine.NET 1.2.0.0
Theme by Mads Kristensen

About the author

Name of author Andrew Rimmer
Software Architect based in London

E-mail me Send mail

Calendar

<<  August 2008  >>
MoTuWeThFrSaSu
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567

View posts in large calendar

Pages

    Recent posts

    Recent comments

    Authors

    Categories


    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2008

    Sign in