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 9:44:44 AM

sohbet

thanks baby

sohbet

10/23/2007 7:49:56 PM

sohbet

thanks a lot..

sohbet tr

12/5/2007 4:05:05 AM

Niyazi

thanks alot.it is very useful for me and my project.
in turkish says "Allah razi olsun"

Niyazi tr

7/16/2008 5:08:26 PM

Matt

I tend to disagree with you on using multiple providers. I think it depends on the project. For a large system, the performance on the database side can be improved by denormalizing and just looking up profile data from one table. The standard profile provider may be ok for storing hair color, by having the overhead of the db having to access another table, a serialized one at that, will create a performance hit for a large scale site.

Matt us

8/13/2008 10:45:42 PM

CodeJunkie

Thanks a ton! I have been using the SqlTableProfileProvider but wasn't aware of the ability to specify a provider for each Property. Super helpful.

CodeJunkie us

Add comment


(Will show your Gravatar icon)  

  Country flag





Live preview

9/7/2008 11:59:30 AM

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

<<  September 2008  >>
MoTuWeThFrSaSu
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

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