How Do I Access the Profile of a Different User Directly in C#?

You may be aware of the new ASP.NET 2.0 Profile feature that allows you to store and retrieve information for the currently logged on user. This Profile feature makes it extremely simple to store user specific information, like a user's address, phone number, or site preferences. (Note: if you're not familiar with ASP.NET 2.0 Profiles check out the section Storing User Profiles in the ASP.NET Quick starts).

But what if you want to access the Profiles data for another user? For example, what if you want to allow a site administrator to change the personal data of all users in your site? The trick to make this possible is to use the ProfileCommon class, which inherits from ProfileBase. This article shows you how you can use this class to access the Profile data for arbitrary users.

Accessing the Current's User's Profile Data

(Note that you can also access a Visual Basic .NET version of this article).

Normally, you can access the Profile data from the Profile class that .NET compiles for you on the fly based on the information stored in the <properties> node under <profile> in the Web.config file. Imagine that there is a key called Street of type String in the Web.config (the sample application that you can download at the end of this article has a Web.config file with the property called Street already set up). You'd access the property like this:

  // Access the property  
  Profile.Country = "SomeStreet";

  // Change its value
  myStreet = Profile.Country;
This gives you strongly typed access to the Profile's properties that are automatically retrieved from and saved to the backing data store, like a SQL Server database.

Accessing a Different User's Profile Data

If you have, for example, a page in the Management section of your site that you use to update the details for one or more users in your database, this code won't work. Every time this code runs, it will only update the current user's Profile; that is, it will only update the Administrator's Profile. To get access to a different Profile for an arbitrary user, you need to create one yourself, and then access its properties. Notice that the term create is a bit of a misnomer. You create an instance of the ProfileBase class, but you don't necessarily create the Profile itself. Only the very first time, when the Profile for the requested user does not exist yet, is the Profile created. In other cases, the existing Profile is retrieved from the database and used. Take a look at the following code to see how this works. First you see the ASPX portion of the code, then you'll see the C# code in the Code Behind file:

<h3>Create New Profile</h3>
  User Name 
  <asp:TextBox ID="txtUserName1" runat="server"></asp:TextBox><br />
  Street
  <asp:TextBox ID="txtStreet" runat="server"></asp:TextBox><br />
  <asp:Button ID="btnSave" runat="server" Text="Create Profile" 
        OnClick="btnSave_Click" /><br />
  <br />
  <br />
<h3>Retrieve Existing Profile</h3>
  User Name
  <asp:TextBox ID="txtUserName2" runat="server"></asp:TextBox><br />
  <asp:Button ID="btnRetrieve" runat="server" Text="Retrieve Profile" 
        OnClick="btnRetrieve_Click" /><br />
  <br />
  <asp:Label ID="lblStreet" runat="server"></asp:Label>

This page contains two areas: one that allows you to create a new Profile by entering a user name and the name of the street. Once you click the Create Profile button, either a new Profile is created or an existing Profile is retrieved from the database for the user name specified in the TextBox txtUserName1. The Profile is then updated with the new information from the txtStreet TextBox.

Once you click the Retrieve Profile button in the second area of the page, the existing Profile is retrieved from the data store, and the Label called lblStreet is updated with the user's data.

To see how this works, take a look at the Code Behind for the page. You'll see two event handlers that deal with the Click events for the two buttons. First, take a look at the code for the Create Profile button:

protected void btnSave_Click(object sender, EventArgs e)
{
  ProfileCommon userProfile = (ProfileCommon) 
          ProfileCommon.Create(txtUserName1.Text, true);
  userProfile.Street = txtStreet.Text;
  userProfile.Save();
}

The first line in this method uses the Create method defined in the ProfileBase class to create a new instance of the ProfileBase class. You'll then need to cast it to a ProfileCommon to access the custom properties defined in the Web.config file. As the first argument, the name of the Profile to create is passed. The second argument determines whether the user is treated as authenticated or not. When you pass false instead, the user will be treated as not authenticated, and you won't be able to access properties that are only accessible by authenticated users (that is, properties that have allowAnonymous="false" in the Web.config).

Once you have a reference to the user's Profile, setting properties is as simple as is normally the case. The only caveat is that you must call Save() on the Profile or otherwise the changes are not persisted. Normally, the ASP.NET 2.0 runtime does this for you automatically in the EndRequest event at the end of the execution cycle of an ASP.NET page, provided that the AutomaticSaveEnabled property is set to True , but with this code, you need to call it yourself.

The final step is to retrieve the data again. Not surprisingly, this code is almost identical:

protected void btnRetrieve_Click(object sender, EventArgs e)
{
  ProfileCommon userProfile = (ProfileCommon) 
            ProfileCommon.Create(txtUserName2.Text, true);
  lblStreet.Text = userProfile.Street;
}

This code creates a new ProfileCommon instance again and then accesses its Street property to update the label.

Accessing the current's user's Profile was already extremely simple, but with the bit of code from this article, accessing arbitrary Profiles is now just has easy. Although this short article demonstrated a quite simple example, it is easy to apply the same principles to everything you know about Profiles, including grouped properties.

Download Files

The download for this article comes as an ASP.NET 2.0 web site with a simple page that demonstrates the code you just saw, and a Web.config file that defines a simple Street property. You'll notice that the download doesn't contain the database; when you run this page, the .NET Framework will automatically create and attach a new database for you that is configured to support the Profiles feature.


Where to Next?

Wonder where to go next? You can read existing comments below or you can post a comment yourself on this article .


Consider making a donation
Please consider making a donation using PayPal. Your donation helps me to pay the bills so I can keep running Imar.Spaanjaars.Com, providing fresh content as often as possible.



Feedback by Other Visitors of Imar.Spaanjaars.Com

On Friday, April 14, 2006 4:35:57 AM Enrique said:
Hi! read your article on "How Do I Access the Profile of a Different User Directly in C#? " What Im trying to do is store user Profile data in SQL database... how would I then call it from this database?

                              Tks,
                              Enrique
On Friday, April 14, 2006 4:27:20 PM Imar Spaanjaars said:
Hi Enrique,

I am not sure I understand what you're asking. When you use the default providers that come with ASP.NET, the data *is* already stored in SQL Server.

Can you describe in a bit more detail what you're trying to accomplish?

Imar
On Friday, April 14, 2006 6:09:49 PM Enrique said:
Hi Imar!
            First I have to point out Im a newbie and well second,  what Im tring to achieve here is the following. I need to have every individual user
(Authorized only) to view data specific to only them and this data should be
viewed from a SQL database either in the website or elsewhere. The data
will be viewed only and constantly updated automatically. \

                    Thanks,
                           ER
On Friday, April 14, 2006 6:50:05 PM Imar Spaanjaars said:
Hi Enrique,

Well, isn't that exactly what the Profile feature does? By default, it'll show data for the current user only.....

Imar
On Friday, April 14, 2006 7:09:53 PM Enrique said:
Hi Imar,
           That part is clear to me.. What Im trying to get at is what if I create a SQL database with lets say UserID , UserPhone, Useraddress and such.  How would I then access this information on that existing SQL database via Profiles?

                                     Tks,
                                         ER
On Friday, April 14, 2006 7:22:59 PM Imar Spaanjaars said:
Right, so you want to expose existing data through the profile?

In that case, take a look at the Table Profile Provider:
http://www.asp.net/sandbox/samp_profiles.aspx?tabindex=0&tabid=1

You'll find two sample providers: SqlTableProfileProvider and SqlStoredProcedureProfileProvider. One allows you to use a table and specify a column mapping, while the second one allows you to use stored procedures and parameter mapping.

HtH,

Imar
On Friday, June 02, 2006 11:08:36 AM Peter Scowcroft said:
A great article - concise & to the point. Thanks.
On Friday, March 23, 2007 12:54:19 PM Robert Mulder said:
There is no such class as ProfileCommon anywhere in the System.Web.Profile namespace, nor does the MSDN documentation know where the class is located.

This results in the above code not compiling for me. What am I missing?
On Friday, March 23, 2007 1:03:21 PM Imar Spaanjaars said:
Hi Robert,

The ProfileCommon class is generated on the fly and inherits from ProfileBase.

http://msdn2.microsoft.com/en-us/library/system.web.profile.profilebase.aspx

For the class to be available, you need to have a valid web.config file with the profile set up.

Cheers,

Imar
On Friday, January 04, 2008 5:40:49 PM Chris said:
THANK YOU so much for explaining this!  I created a procedure that exported all of our old user information from Access to our new SQL membership database, and couldn't figure out how to create the individual profiles for each user.  THANK YOU!
On Wednesday, January 23, 2008 11:13:07 AM Davide said:
Nice article Imar.

Regards
Davide
On Friday, November 07, 2008 10:05:51 AM Fergus said:
Thanks very much, I've spent hours looking for this info.  You code does exactly what I wanted.  Fantastic!

Regards
Fergus
On Thursday, November 13, 2008 10:07:51 AM Dima said:
Can one tell the way to access (at least read) the user profile custom properties (added via web.config section) within the SQL. Because they are stored in aspnet_Profile.PropertyValuesString/PropertyValuesBinary and there's no easy way to parse it in SQL w/o calling some CLR SP or function (that is undesirable).
On Thursday, November 13, 2008 8:22:27 PM Imar Spaanjaars said:
Hi Dima,

You can't really. Because of the format the data is stored in, you need to parse it before you can make any sense out of it. Embedded .NET in SQL is one option, but not ideal indeed.

You could use one of the table or stored procedure based providers which give you full control over the data structure:

http://www.asp.net/downloads/sandbox/table-profile-provider-samples/

Hope this helps,

Imar
On Wednesday, February 18, 2009 6:05:13 AM Kavya said:
Nice article.
I want to have an admin user who has full rights to add/modify/update the profile of all the other users in the database. In the code given by you, any user can change the profile of other users. How to go about authenticating and authorising only one user to have these privileges of changing others profiles?
On Wednesday, February 18, 2009 7:35:05 PM Imar Spaanjaars said:
Hi Kavya,

You can use ASP.NET URL authorization, Membership and Roles for this. Check out this link for more ideas: http://www.google.com/search?hl=en&q=asp.net+url+authorization&aq=f&oq=

Cheers,

Imar
On Monday, October 19, 2009 9:48:56 AM Johnny Hansen said:
Hey Imar..

Great article.
Im trying to save profile information for another user. I have no trouble getting the profileinfo, but when i try to alter it, and save the new information, I cant get it to save it.
Im using:

ProfileCommon UserProfile = Profile.GetProfile(Username);
        UserProfile.Fornavn = T_Surname.Text;
        UserProfile.Efternavn = T_Lastname.Text;
        UserProfile.Telefon = T_Phone.Text;
        UserProfile.Save();

Its not saving.. what am i doing wrong?

Thx again :-)
On Monday, October 19, 2009 6:30:13 PM Imar Spaanjaars said:
Hi there,

You're using Profile.GetProfile while my sample code uses ProfileCommon.Create and a cast to ProfileCommon.

Cheers,

Imar
On Tuesday, October 20, 2009 7:58:56 AM Johnny Hansen said:
Hey Imar.

Sorry.. My bad.. I should have read the whole thing carefully instead of just picking out some code and presume I know the rest :-D

Thanks again for some great articles. I was especially happy about the one, that shows me how to use Access db for membership and profiles :-D

Cheers
  Johnny
On Monday, January 18, 2010 10:29:24 AM Radek said:
Thak you so much for this example :)
On Saturday, June 12, 2010 7:38:41 AM Bryan said:
Finding this site gives me some new hope. For the several, I've been stuck on an extremely stubborn problem which MS "bug services" can't even help me figure out. I need someone more intimately familiar with the SqlTableProfileProvider.

The problem is that a SQL statement produced by the provider has two UserID columns; this happens in the SetPropertyValues section of SqlTableProfileProvider:

Dim sqlCommand As New StringBuilder("IF EXISTS (SELECT 1 FROM ")

The suggested solution from the "bug people" was to delete the UserID profile property from my web.config file, but when I do that, it totally messes up the Where criteria in the ListView I'm using. Any ideas? I'd be glad to provide any code samples, etc.
On Saturday, June 12, 2010 7:56:45 AM Imar Spaanjaars said:
Hi Bryan,

I don't understand what you're asking. I don't see what you mean by two UserID columns, I don' see how the IF EXISTS is related and I don't see how all of this would affect your ListView.

I'll be happy to help but need lots more detail Can you start a post here: http://p2p.wrox.com/index.php?referrerid=385 and provide a way more detailed problem description?

Cheers,

Imar
On Sunday, June 13, 2010 6:00:51 AM Bryan said:
After all this time, I think I've finally figured out the problem. I needed a parameter for my Where statement to allow my users to perform an update. In looking for the best parameter to use, I mistakenly chose Profile. This is how I had it set up:

Under Profile / Properties in web.config (brackets removed):

add name="UserID" defaultValue="null" customProviderData="UserID;uniqueidentifier;true"/

    Protected Sub lsvProfile_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles lsvProfile.Init
        Dim user As MembershipUser = Membership.GetUser()
        Dim UserID As Guid = Membership.GetUser().ProviderUserKey
        Profile.UserID = UserID.ToString()
    End Sub

This was adding a second UserID column to the query's update statement (which I believe is generated in SqlTableProfileProvider), like so:

IF EXISTS (SELECT 1 FROM [myTableName] WHERE UserId = @UserId) BEGIN UPDATE [myTableName] SET [snip] UserID=@Value27, [snip] @LastUpdatedDate) END

In effect, then, the "Profile.UserID = UserID.ToString()" statement was attempting to reassign UserID a new value through the Profile system, and that's where the error was coming from.

Instead, I replaced Profile.UserID=... with Session("UserID")=... and chose Session as the type of parameter.

My last question: Since Session parameters take a bit of overhead, is there any other parameter that I could use in its place, to reference the UserID guid value?
On Sunday, June 13, 2010 6:03:23 AM Bryan said:
Sorry, my last post ran all together--not sure why it did.
On Sunday, June 13, 2010 8:50:24 AM Imar Spaanjaars said:
Hi Bryan,

You can execute Membership.GetUser() to get the user and then take its ProviderUserKey. However, that requires an additional database call so may not improve performance.

You could store the ID in a cookie, but that's not secure. So, I would either keep it in a session or get it from the current user.

Cheers,

Imar
On Tuesday, June 15, 2010 1:16:43 AM Bryan said:
When you say "get it from the current user," is there a difference between that and Membership.GetUser().ProviderUserKey? If so, what is the syntax?
On Tuesday, June 15, 2010 8:45:33 AM Imar Spaanjaars said:
Hi Bryan,

No, I was indeed referring to Membership.GetUser().

Cheers,

Imar
On Tuesday, November 23, 2010 8:50:22 AM koaik said:
hi every body,,i made a new web app that has 2 page one as a login page and the other is the main page for users can save personal info..i added the profile tag in web.config with th data i need as follows
[profile]
      [properties]
        [add name="name" allowAnonymous="false"/]
        [add name="email" allowAnonymous="false"/]
        [add name="smoker" allowAnonymous="false"/]
        [add name="status" allowAnonymous="false"/]
        [add name="picURL"  allowAnonymous="false" /]
      [/properties]
  [/profile]
i created two users using the asp.net configuration tools..the problem is when iam logging with the first user and saving data the close the browser then logg with the other user the data of the first on appears..as if iam logging as anynomous user then modifying-->saving then log with the first user the information of the secon one appears and so on..

the code iam using for saving is:

protected void Button1_Click(object sender, EventArgs e)
    {

ProfileCommon p = (ProfileCommon)ProfileCommon.Create (Profile.UserName, true);
   p.name=TextBox1.Text;
   p.email = TextBox2.Text;

   p.Save();

}

and the code for retrieving data from the profile is:

protected void Page_Load(object sender, EventArgs e)
    {

        if (!IsPostBack)
        {

            ProfileCommon p = Profile.GetProfile(Profile.UserName);
            TextBox1.Text = p.name;
            TextBox2.Text = p.email;

          
        }
        does any on knows wat is happening with me...thnx
On Tuesday, November 23, 2010 8:53:10 AM Imar Spaanjaars said:
Hi koaik,

Is this a web application or a web site? Did you check the value of Profile.UserName? Maybe it's empty?

Imar
On Tuesday, November 23, 2010 8:56:33 AM koaik said:
hi imar,

its a website...i check by inserting a break piont its something like that:  Profile.UserName = "d62de890-f1df-46ce-9246-1c96229155de"
On Tuesday, November 23, 2010 8:59:11 AM Imar Spaanjaars said:
Hi koaik,

In that case, it seems you're indeed creating a profile based on the anonymous cookie which is probably not cleared when you log out.

Have you tried creating a profile based on the UserName instead?

Imar
On Tuesday, November 23, 2010 9:04:24 AM koaik said:
hi imar,

how would i create a profile based on username?

i just opened the web.config and added the above tag..how would i created a profile based on the anonymous cookie?

koaik,
On Tuesday, November 23, 2010 9:08:10 AM Imar Spaanjaars said:
You would use User.Identity.Name instead of Profile.name.

What I don't get is why you're creating the profile explicitly. My example in this article is used to demonstrate how to access someone else's profile. In your case, you need to access the current user's profile. So why go through all this trouble and not simply use Profile.name = "Whatever"?

Imar
On Tuesday, November 23, 2010 9:20:36 AM koaik said:
hi imar,

sorry for my long time discussion,well i used the user.identity.name and i found it empty also the Profile.name is empty...my purpose about this website is to see the result of using profile..like you said the current's user profile..but i cant configure out the problem.

regards
On Tuesday, November 23, 2010 9:24:06 AM Imar Spaanjaars said:
User.Identity.Name shouldn't be empty when you log in using the Membership services.

This is getting a bit too much to discuss here. Can you post this on the Wrox forum and supply the full code for your two pages and config file?

http://p2p.wrox.com/index.php?referrerid=385

Cheers,

Imar

Talk Back! Comment on Imar.Spaanjaars.Com

I am interested in what you have to say about this article. Feel free to post any comments, remarks or questions you may have about this article. The Talk Back feature is not meant for technical questions that are not directly related to this article. So, a post like "Hey, can you tell me how I can upload files to a MySQL database in PHP?" is likely to be removed. Also spam and unrealistic job offers will be deleted immediately.

When you post a comment, you have to provide your name and the comment. Your e-mail address is optional and you only need to provide it if you want me to contact you. It will not be displayed along with your comment. I got sick and tired of the comment spam I was receiving, so I have protected this page with a simple calculation exercise. This means that if you want to leave a comment, you'll need to complete the calculation before you hit the Post Comment button.

If you want to object to a comment made by another visitor, be sure to contact me and I'll look into it ASAP. Don't forget to mention the page link, or the QuickDocId of the document.

For more information about the Talk Back feature, check out this news item.