LogoASPAlliance: Articles, reviews, and samples for .NET Developers
Understanding the Profile Object of ASP.NET Version 2.0 (Beta 1)
by Terry Voss
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 22747/ 73


[Download Sample Project]

Why is the Profile class (formerly called Personalization) one of the most interesting new features of ASP.NET Version 2.0?  Unlike membership, roles, and other personalization-related areas, it has much potential for general increase in state capability that is more efficient than we have had before in the inherently stateless web application.

Generally it is accepted good architectural advice to keep your application as stateless as possible to make it easy to scale. Yet state is what mainly differentiates web development from desktop development in capability, so it could potentially be very important to all aspects of web development.  The Session object has been so valuable, and Profile has the potential to be an object that works alongside session to improve a web application's control of state.

Why not just create a session with a two-year timeout? The session is very important for authentication and authorization.  Running out to lunch and leaving your browser open could cause a compromise of all the company's passwords or other damage. So wouldn't it be nice if session could be used for that security purpose and if we had a strongly-typed object, which is efficient in memory and has an infinite timeout that developers can control?

This is a simple description of the Profile object. Now, because the Profile object is strongly typed, at runtime we cannot add properties as we could with Session.  There is no dynamic runtime change of structure with this Profile object. Planning ahead is the way to go here.

Also, Profile is more intelligent and efficient in the way it stores and reads data. Session always loads the whole session dictionary when you only want to query one value. Profile only looks up data when it is used.

Why do I call it an object instead of a class? Like the Session object, the Profile object is readily available to our web forms. As the session object is held in the HttpContext.Current.Session property, the Profile object is held in the HttpContext.Current.Profile property. This means if you are not in a Page-derived class, then import System.Web.HttpContext, and use Current.Profile to access its properties.

So setting and reading a Profile property from a page object method is as simple as:

Profile.Name = "MyName" 
Dim MyName as String = Profile.Name 

And if you are not in a Page-derived class but in a custom class method:

Current.Profile.Name = "MyName" 
Dim MyName as String = Current.Profile.Name

Comparing Profile and Session:
1) Both objects store separate data for each user of your web application without the developer having to worry about coding for such.
2) Session often needs a small timeout value to protect the user enough, while Profile only ends at the developer's discretion.
3) Profile allows control over clearing by inactive profiles versus active ones, time periods, etc., while session is one or all.
4) Profile is strongly typed and Session is not.
5) At runtime, a key can be added to Session, a property for Profile must be designed in before runtime.
6) Session must load the entire dictionary to read only one value, while Profile can read just one property efficiently (more scalable).
7) Both can store any kind of object. 

Now Session can focus on authentication authorization concerns, as we have a stronger candidate for state management.

Basic Knowledge

[Download Sample Project]

The System.Web.Profile namespace contains seventeen types:
 1) DefaultHttpProfile (inherits HttpProfileBase, provides untyped access to Profile properties)
 2) HttpProfileBase (provides untyped access to Profile properties)
 3) HttpProfileGroupBase (provides untyped access to group Profile properties)
 4) ProfileAuthenticationOption (enumeration: All, Anonymous, Authenticated)
 5) ProfileAutoSaveEventArgs (inherits EventArgs)
 6) ProfileEventArgs (inherits EventArgs)
 7) ProfileInfo (holds info about one user's profile)
 8) ProfileInfoCollection (holds info about all users' profiles)
 9) ProfileMigrateEventArgs (provides event data for the MigrateAnonymous event of the ProfileModule class)
10) ProfileModule (noninheritable/sealed; implements IHttpModule)
11) ProfileProvider (mustinherit)
12) ProfileProviderAttribute (noninheritable/sealed; inherits Attribute)
13) ProfileProviderCollection (usual collection members, count, add)
14) SettingsAllowAnonymousAttribute (noninheritable/sealed; inherits Attribute)
15) AccessProfileProvider (I couldn't successfully instantiate this; could be Microsoft-used class)
16) SqlProfileProvider (I couldn't successfully instantiate this; could be Microsoft-used class)
17) ProfileManager (allows management of profile info, like delete types, find types, get numbers of types, of profiles, most members are shared/static)

Use this important last class to manage either type of storage: MS Access or MS SQL Server, as it has many valuable methods. Two other valuable classes are the ProfileInfo and ProfileInfoCollection for reporting the user state status as you will see in later code samples.

If you create a new web project and immediately in the default.aspx file code-beside you type the following, you will get squiggles regarding Name member not existing for the Profile object.

Dim x as string = Profile.Name
With Visual Studio, go to the Website menu and choose the ASP.NET Configuration Option, choose Profile, choose Add Property, add a Name property, and Save. Now go back to your code. The squiggles are gone. This is because at least the following entries have been added to the web.config file.
<?xml version="1.0" encoding="utf-8"?>
<profile inherits="System.Web.Profile.HttpProfileBase, System.Web,
                   Version=2.0.3600.0, Culture=neutral,
    <add name="MyName" type="System.String" />

If you don't have Visual Studio, use the Profile tab of the Web Site Administration Tool (WAT) to manage how your site collects personal information about visitors. Profile properties represent data specific to a particular user. Using profile properties enables you to personalize your Web site for individual users. The address for this web application will be: http://localhost/AppFolderNameInWebsites/Webadmin.axd

The Profile property groups allow you to group related profile properties together within a collection. For example, you may choose to group the Title property along with other properties such as First, MiddleInitial, Middle, Last and Suffix in a property group called Name. In this example, you would set the value for the Suffix property with the following line of code:

Profile.Name.Suffix = "Junior"

Here is the associated web.config entries:

 <group name="Name"> 
   <property name="Title" type="System.String "/> 
   <property name="First" type="System.String "/> 
   <property name="Middle" type="System.String "/> 
   <property name="Initial" type="System.String "/> 
   <property name="Last" type="System.String "/> 
   <property name="Suffix" type="System.String "/> 
 <group name="Address"> 
   <property name="Street" type="System.String"/> 
   <property name="City" defaultValue="Redmond" type="System.String"/> 
   <property name="State" defaultValue="WA" type="System.String"/> 
   <property name="Zip" type="System.String"/> 

You can also create a custom type that you use as a Profile property. For example, you might have a class named ShoppingCart in a namespace called Sales that you can specify as a Profile property and can then associate with each user in your application. So ShoppingCart can be a collection of ItemOrder classes.

If you specify a custom type for your profile property, you must specify the fully-qualified class name for the type so that ASP.NET can instantiate the class when the application runs. If the ShoppingCart class is defined in your Code folder with a namespace of Sales, you would enter the following in the fully-qualified type name box under the custom data type option:


You can also enable tracking by a generated unique ID for anonymous users of your site. This ID is stored in a cookie on the user's computer.

Basic Example

[Download Sample Project]

Let's create a ShoppingCart class and use it in Profile.  First, we create an ItemOrder class with a simple version of an order, then a collection container for it, and then the code using it.  Note that if you just declare two public fields for ProductID and Quantity and not method properties, your collection of ItemOrder classes will not automatically bind to the GridView or DataGrid. Also note the two constructors or constructor overload as they come into importance later.

ItemOrder Class
<Serializable()> Public Class ItemOrder

Sub New()
End Sub

Sub New(ByVal qty As Integer, ByVal product As Integer)
  _quantity = qty
  _productID = product
End Sub

Private _quantity As Integer
Private _productID As Integer

Public Property Quantity() As Integer
    Return _quantity
  End Get
  Set(ByVal Value As Integer)
    _quantity = Value
  End Set
End Property

Public Property ProductID() As Integer
    Return _productID
  End Get
  Set(ByVal Value As Integer)
    _productID = Value
  End Set
End Property

End Class

Shopping Cart Class
Imports System.Collections.generic

<Serializable()>Public Class ShoppingCart : Inherits List(Of OrderItem)
End Class

Code-Beside Class
Imports System.Web.Profile

Partial Class viewprofile_aspx

Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  If Not IsPostBack Then
    Profile.Cart = New ShoppingCart
  End If
End Sub

Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
  Dim item As New ItemOrder(quantity.Text, product.Text)
  GridView1.DataSource = Profile.Cart
End Sub

Web.config Section
<profile defaultProvider="Developer2 Data">
    <add name="Cart" type="MyNamespace.ShoppingCart" serializeAs="Binary" allowAnonymous="true" />

Note the little code for ShoppingCart; because it inherits from a generic List dedicated to only ItemOrder objects, all we need is the inherited Add, Remove, Count, etc. methods for a cart.  Note then that only two lines of code add an item to the cart with the button click.  Two lines bind the result to the GridView1 control. 

Both custom objects must have the attribute for Serializable affixed since this information must be serialized by the Profile object. There are two methods of serialization with the default being XML serialization. I have selected binary serialization in the above web.config entry at the suggestion of Dino Esposito in his book linked below (page 111). He was using (it seems) pre-Beta 1 code, and I had no trouble with collections and Profile with either serialization type, except for automatic referencing.

In Beta 1, if you create your custom classes in the code folder it is a dynamically compiled file, but the dynamically generated assembly is not automatically referenced. Therefore, currently in Beta 1, you will get Intellisense for your new cart after putting it into the website menu's ASP.NET configuration option's Create Profile property area, but you will get a reference error. Currently you will have to manually compile your own classes to a DLL that you place into the bin folder under your application's bin directory. I placed my two .vb files into the bin folder and used the following compile statement in a batch.bat file:

cd "c:\websites\profile\bin\"
/out:ShoppingCart.dll /target:library /optimize /recurse:*.vb 

The shopping cart then works fine, showing the added items in the GridView1 control piling up. When I took the isSerializeAs="Binary" out, so that the default serialization would be used, I got an error indicating that ItemOrder class did not have an empty default constructor. I added the binary serialization option back, and things worked again.

The other constructor is added so that I can create an ItemOrder instance with one line of code. I am hoping very much that, by Beta 2, the custom type referencing will be automatic (I have recently confirmed with Microsoft that these problems with the custom data type will be fixed by beta2). If you note the one line in the Page load event, I wish the Profile property allowed me to check that I want a new instance of my type put into the Profile custom property, so I don't have to do that line like the simple types do.


[Download Sample Project]

So the ASP.NET Configuration interface allows you to design user properties, and this information goes into the web.config file. The Profile object then knows what is defined and where to go to get it in your chosen provider or data store.

One application of the Profile object is to only use session for authentication and authorization purposes and do data storage for a user in the Profile object. So change each:

session("MyVar") = 1
profile.MyVar = 1
x = session("MyVar")
x = profile.MyVar

I think the real potential for website statefulness must be measured by using a number of complex classes like a ShoppingCart and stress testing it with Microsoft Application Center, but that must wait until the RTM (Release to Manufacture) version is available. Could your website soon out-personalize Amazon?

New Personalization Features in ASP.NET Whidbey
Managing User Profiles in ASP.NET 2.0
More Whidbey Changes: Personalization/Profile

Books:  (I own the following books below and therefore can attest that their quality is good on Version 2.0 new features)
Note: The Esposito book has more detail on Profile.

1. A First Look at ASP.NET v 2.0
by Alex Homer, et al (Paperback)
Avg. Customer Rating: 4.5 out of 5 stars
2. Introducing ASP.NET 2.0
by Dino Esposito; (Paperback)
Avg. Customer Rating: 3.0 out of 5 stars


Product Spotlight
Product Spotlight 

©Copyright 1998-2021  |  Page Processed at 2021-10-27 2:37:25 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search