An Extended Look at the Profile Object - Part 2
page 2 of 4
by Bilal Haidar
Feedback
Average Rating: 
Views (Total / Last 10 Days): 30096/ 68

Specifying a Custom Object in the Profile Configuration Section

Suppose we are developing an application for teachers in a school that tracks which of its students have registered for a certain event in the school. A teacher should be able to add a student to the list of those participating in the event, remove a student, and so on.

For this functionality, we will create a StudentList class that is a collection of Student types. A teacher can add and remove any student from the StudentList collection. Storing this class in a Profile object means that the student list will be available automatically every time the teacher logs in to his or her account.

Listing 2 shows a Profile configuration section that defines a Profile property whose type refers to a class of type StudentList. In addition, we see a new serializeAs attribute that is used to persist the StudentList class using binary serialization.

Listing 2. Profile Configuration Section with a Custom Object

<anonymousIdentification enabled="true"/>
<Profile enabled="true">
<properties>
<add name="StudentList" type="StudentList" allowAnonymous="true" serializeAs="Binary" />
</properties>
</Profile>

Listing 3 shows the code for the implementation of the StudentList class. This class has methods to add and remove student records from the list. It also contains a property that represents the number of students’ records in the student list.

Listing 3. StudentList

using System;
using System.Collections;
[Serializable]
public class StudentList : IEnumerable
{
private Hashtable _StudentRecords = new Hashtable();
//Return Student Records
public Hashtable StudentRecords
{
get { return _StudentRecords; }
}
// Return the number of student records in the student list
public int AllRecords
{
get
{
int Count = 0;
foreach (StudentRecord sr in _StudentRecords.Values)
{
Count++;
}
return Count;
}
}
// Add a new Student Record to the student list
public bool AddRecord(int StudentId, StudentRecord sr)
{
StudentRecord _SR = (StudentRecord)_StudentRecords[StudentId];
if (_SR == null)
{
_StudentRecords.Add(StudentId, sr);
return true;
}
// Student record is already in the list
return false;
}
// Remove a student record from the list if found
public bool RemoveRecord(int StudentId)
{
StudentRecord _SR = (StudentRecord)_StudentRecords[StudentId];
if (_SR == null)
{
// The record to be deleted is not in the list.
return false;
}
// Student record is in the list
_StudentRecords.Remove(StudentId);
return true;
}
// Allow to use foreach by implementing the IEnumerable Interface.
public IEnumerator GetEnumerator()
{
for ( int i = 1; i <= _StudentRecords.Count; i++ )
yield return _StudentRecords[i];
}
}

As we have seen in the above listing, we have used a custom object called StudentRecord which represents one student record. Listing 4 below presents the implementation of that custom object.

Listing 3. StudentRecord

using System;
using System.Data;
using System.Configuration;
[Serializable]
public class StudentRecord
{
#region Private Fields
private int _StudentId;
private string _FirstName;
private string _LastName;
#endregion
#region Constructor
public StudentRecord(int StudentId, string FirstName, string LastName)
{
_StudentId = StudentId;
_FirstName = FirstName;
_LastName = LastName;
}
#endregion
#region Properties
public int StudentId
{
get { return _StudentId; }
}
public string FirstName
{
get { return _FirstName; }
}
public string LastName
{
get { return _LastName; }
}
#endregion
}

The above two classes should be placed in the App_Code directory, which is a system directory that contains all custom objects created in the Web application. This directory will be compiled into a single DLL at runtime and all the custom objects placed inside it will be accessible to all the ASP.NET pages in the application.

Also notice that each class has an attribute of Serializable. This attribute should be set because both objects must be serialized in order to be stored in a Profile object.

Listing 5 presents the page that allows each teacher to add a new student record to the StudentList (See Figure 1).

Figure 1. Add Record

Listing 5. AddRecord.aspx

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class AddRecord : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
PlaceHolder1.Visible = false;
}
protected void Button1_Click(object sender, EventArgs e)
{
// New instance of StudentRecord
StudentRecord sr = null;
// Studen record
int _Id;
bool TempId = int.TryParse( TextBox3.Text, out _Id );
if (TempId && 
!string.IsNullOrEmpty(TextBox1.Text) &&
!string.IsNullOrEmpty(TextBox2.Text)
}
sr = new StudentRecord(_Id, TextBox1.Text, TextBox2.Text);
else
// If one of the field are wrong we return 
// and don’t insert the record
return;
// Initialize the list if empty
if (Profile.StudentList == null)
Profile.StudentList = new StudentList();
// Show Place holder
PlaceHolder1.Visible = true;
// Add student record to list
if (Profile.StudentList.AddRecord(_Id, sr))
{
// Display the Profile proeprties 
string TextToDisplay = "Student with Id <b>" + _Id + "</b> is added to the list <br />";
PlaceHolder1.Controls.Add(new LiteralControl(TextToDisplay));
PlaceHolder1.Controls.Add(new LiteralControl("<hr /><br />"));
}
else
PlaceHolder1.Controls.Add(new LiteralControl("Student is already in the list"));
}
}

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="AddRecord.aspx.cs" Inherits="AddRecord" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
 "<a href="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd</a>">
<html xmlns="<a href="http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml</a>" >
<head runat="server">
<title>Add Record Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<div>
<h2>
Teacher Administration Area</h2>
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
<br />
<br />
Student Id :&nbsp;
<asp:TextBox ID="TextBox3" runat="server"></asp:TextBox><br />
<br />
First Name :
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<p>
Last Name :
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox></p>
<p>
&nbsp; &nbsp;
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Add User" /></p>
</div>
</div>
</form>
</body>
</html>

Listing 6 presents the page that allows each teacher to remove a student record from the StudentList (See Figure 2).

Figure 2. Remove Record

Listing 6. RemoveRecord.aspx

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class RemoveRecord : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
PlaceHolder1.Visible = false;
}
protected void Button1_Click(object sender, EventArgs e)
{
// Studen record
int _Id;
bool TempId = int.TryParse(TextBox3.Text, out _Id);
// Show Palce holder
PlaceHolder1.Visible = true;
if (TempId)
{
// Add student record to list
if (Profile.StudentList.RemoveRecord(_Id))
{
// Display the Profile proeprties 
string TextToDisplay = "Student with Id <b>" + _Id + "</b> is removed from the list <br />";
PlaceHolder1.Controls.Add(new LiteralControl(TextToDisplay));
PlaceHolder1.Controls.Add(new LiteralControl("<hr /><br />"));
}
else
PlaceHolder1.Controls.Add(new LiteralControl("Student is not found in the list"));
}
else
PlaceHolder1.Controls.Add(new LiteralControl("Student Id is not a valid Id"));
}
}

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="RemoveRecord.aspx.cs" Inherits="RemoveRecord" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
 "<a href="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd</a>">
<html xmlns="<a href="http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml</a>" >
<head runat="server">
<title>Remove Record Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<div>
<div>
<h2>
Teacher Administration Area - Remove Record</h2>
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
<br />
<br />
Student Id :&nbsp;
<asp:TextBox ID="TextBox3" runat="server"></asp:TextBox><br />
<p>
&nbsp; &nbsp;
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Remove Student" /></p>
</div>
</div>
</div>
</form>
</body>
</html>

Finally, the page in Listing 7 below displays a list of all students’ records that have been previously added using the AddRecord.aspx page (see Figure 1). We have looped through all the student records stored within the StudentList property of the Profile object and displayed them on the page.

Figure 3. Display StudentList records

Listing 7. Displaying StudentList records

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class DisplayRecords : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
PlaceHolder1.Controls.Add(new LiteralControl("There are " + Profile.StudentList.AllRecords + " student(s) in the list: <br /><br/>"));
foreach (StudentRecord sr in Profile.StudentList)
{
PlaceHolder1.Controls.Add(new LiteralControl("Student Id : " + sr.StudentId + "<br />"));
PlaceHolder1.Controls.Add(new LiteralControl("First Name : " + sr.FirstName + "<br />"));
PlaceHolder1.Controls.Add(new LiteralControl("Last Name &nbsp;: " + sr.LastName + "<br /><hr /><br/>"));
}
}
}

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="DisplayRecords.aspx.cs" Inherits="DisplayRecords" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
 "<a href="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd</a>">
<html xmlns="<a href="http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml</a>" >
<head runat="server">
<title>Display All Student Records</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h2>
Teacher Administration Area - Display Records</h2>
<p>
&nbsp;</p>
<p>
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
&nbsp;</p>
</div>
</form>
</body>
</html>

 


View Entire Article

User Comments

Title: Property IsDirty when inheriting ProfileBase (2nd option)   
Name: AiM
Date: 2006-07-20 11:33:35 AM
Comment:
I tried both versions, when I set the configuration in the config file it works ok, but when I implement the class that inherits from ProfileBase the changes aren't saved. I overrided the Save method just to check for the value of the IsDirty property, and it is false.
How this should work, are there other details for the inherited option I don't know?
Title: Re:   
Name: Bilal Haidar [MVP]
Date: 2005-12-01 5:21:55 AM
Comment:
Hello:
You should wait for Part3 of this series to know everything about the database and etc...

Regards
Title: Where is Database ?   
Name: Zeeshan Ali
Date: 2005-12-01 5:17:02 AM
Comment:
You didn't specify the database to which the profile will persist. Where the Peofile data is being persist ?? Cookies ? or What ?
Title: Win app   
Name: Anders H
Date: 2005-11-30 4:44:45 PM
Comment:
If you want to use this example, in a web app,you add data and work with it in a webb app, then you want to get this data in a windows service app for example mailing things based on the items in this profile data, then you need to get to this data from a win app, how do you do that???
Title: Re:   
Name: Bilal Haidar [MVP]
Date: 2005-11-30 1:29:12 AM
Comment:
Well, the Profile object has its own HttpModule events. The way it works is as follows:
At runtime, the configuration section of the profile object in the Web.config will be tranformed into a strongly typed object which is then added to the HttpContext.
At the beginning of the request, the profile data are loaded from database, then at the end of the request, if the data is dirty (has been changed) it will be saved back. Saving data at every request is a matter of a Flag you can configure.
Hope that answers you well.

Regards
Title: One of the more useful articles I've seen in a long time!   
Name: Colin
Date: 2005-11-29 6:12:03 PM
Comment:
I just learned how to create a custom Role- and Membership- Provider and I saw no mention of this class anywhere! I wish I'd known because I spent a long time digging for something like this, and ended up coming up with a custom implementation using an HttpModule and Session.

Have you discovered in your study of the class what the default persistance mechanism is the profile? Is it stored in the user's context or persisited, like forms authentication info, in a secured cookie or something?
Title: Re:   
Name: Bilal Haidar [MVP]
Date: 2005-11-29 1:51:35 AM
Comment:
Hi to all:
Profile object can be thought of as advanced session object. In windows applications, no need for that concept, so it is ot available there.
Thanks for the comments.

Regards
Title: good article   
Name: DotNETKans
Date: 2005-11-29 12:21:16 AM
Comment:
hi Bilal,

Good article mate. Keep it up.
Title: From a win32 app   
Name: Anders H
Date: 2005-11-28 12:39:01 PM
Comment:
How can i access this from an win32 application, it complain on profile object others than ordinary type eg. string, int etc....??

Product Spotlight
Product Spotlight 





Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2019 ASPAlliance.com  |  Page Processed at 2019-11-14 6:50:47 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search