ASP.NET 2.0 Profile Feature

K. Scott Allen recently published a good post on the new ASP.NET 2.0 Profile system.  The profile system provides an easy way to store and retrieve properties about users on your sites -- both logged-in and anonymous.  It can save you time and effort in providing a richer personalized experience for people using your site.

I published a sample a few months ago that showed how to take advantage of the profile system as part of a site log-in process that you might want to check out.

Hope this helps,

Scott

P.S. I have occasionally heard people say - "personalization is cool, but I'm just building an Intranet site so that isn't so important".  One simple scenario I always point out is the common scenario of saving previous data queries/reports.  You can do this now in only a few lines of code -- and the difference in user-experience can really be dramatic.

 

42 Comments

  • Scott, I havent dug too deeply into personalization, but are there API for querying personalization data?



    For example, if I were to keep the user's newsletter optin status in the Profile, is there an easy (or otherwise) way for me to retrieve all users who have opted in?



    Thanks!

  • Yes, but what about it loading all the personalization data before each page load?? That is a little overkill. What to do with something like 'settings' for a user. Something that does not change except from certain pages. It is something I want to load up once when the user logs in, not pull from the database on every page!



    In the example above about saving previous reports/queries. You would not want to have to load all that data on every page load!

  • I'm looking here and there for information regarding the ASPNETDB.MDF database files (created under SQL Express): I just want to know what will happen to my users and profile settings when I will migrate my local website to the one provided by my ISP. Since my ISP's SQL server 2005 may contain numerous ASPNETDB.MDF (on behalf of other websites), how will I be able to continue to manage my own data without mixing it with the ASPNETDB.MDF database files of other websites?



    Your answer is very important for me because this question is harassing me since too many days and evenings.



    Thanks!



    Marie-Claire

  • Hi Wayne,



    The profile data is actually only ever loaded when someone tries to access the profile properties. So if you don't actually write code against the Profile object on a page, it will never be loaded (it uses a lazy-load pattern -- so only loads on first use).



    This should give you exactly the behavior you are looking for, and avoid the extra cost of always doing it on each request.



    Hope this helps,



    Scott

  • Some my thougths about personalization of controls into body of page:

    I did next for personalisation of ascx controls:

    for everyone control per page I compare the role of active userID with the controlname.ID directly on client side or on server side without additional retrieving that roles from database before every new page creating. I had next:

    - session with ClientID and roleID (i got it when application start when coockie is, or by retrieving first tiime from database after every new LogIN)

    - nameofcontrol consists from two parts: nameofcontrol and roleid of authentificated user.



    In result all my clients programms can easily to retrieve the rule of working for every part of page content by retrieving roleid from name of control.(it is very easy and notneed postback that roleid from server side)



    Sincerely, LukCAD

  • Personalization seems pretty good, but it doesn't appear to have an administrative overview.



    I wanted, for example, to view the profiles of people on an administrative form, such as their preferred name, or other custom data that is in the profile.



    It doesn't seem that possible to extract all of this easily, through an ObjectDataSource or otherwise..



    Glyn

  • Hi Glyn,



    You can use the System.Web.Profile.ProfileManager class to gain access to the system's profile data.



    ProfileManager.GetNumberOfProfiles() will return the number of profiles in the system.



    You can then use ProfileManager.GetAllProfile() to page through these profiles and get access to their values (if you hook this up to an ObjectDataSource and a GridView it should be pretty easy).



    You could then build an admin page that provided access to the what you are looking for.



    Does this help answer your scenario? Let me know if you want me to provide more details.



    Thanks,



    Scott

  • You cannot retrieve custom properties! I'm having this problem and it seems that the ASP.NET Microsoft team didn't think about this!!



    The profilemanager class has the following methods:



    - DeleteInactiveProfiles. Enables you to delete all profiles older than a specified date.

    - DeleteProfile. Enables you to delete a profile associated with a specified username.

    - DeleteProfiles. Enables you to delete a set of profiles.

    - FindInactiveProfilesByUserName. Returns a collection of ProfileInfo objects that represent profiles that have been inactive since a specified date and match a specified name.

    - FindProfilesByUserName. Returns a collection of ProfileInfo objects that represent profiles that match a specified username.

    - GetAllInactiveProfiles. Returns a collection of ProfileInfo objects that represent profiles that have been inactive since a specified date.

    - GetAllProfiles. Returns a collection of ProfileInfo objects that represent all profiles.

    - GetNumberOfInactiveProfiles. Returns an integer that represents the number of profiles that have been inactive since a specified date.

    - GetNumberOfProfiles. Returns an integer that represents the total number of profiles.



    None of these methods return a complete profile, although many of the methods return a collection of ProfileInfo objects. The ProfileInfo object represents the following profile properties:



    - IsAnonymous. A Boolean value that represents whether or not the profile is associated with an anonymous or authenticated user.

    - LastActivityDate. A date and time that represents the last time the profile was accessed.

    - LastUpdatedDate. A date and time that represents the last time the profile was updated.

    - Size. An integer value that represents the size of the profile as stored by the profile provider.

    - UserName. A string that represents the user associated with the profile.





    I would like to retrieve all the custom properties that I've configure on the Web.config and none of the available methods allows to do this!!!

    WHY MAKE PROFILES AVAILABLE IF THEN THEY DON'T SUPPLY ANY METHOD TO RETRIEVE THE CUSTOM PROPERTIES?



    Can anybody tell me how can I retrieve all users that have a profile and bind all custom properties to a gridview?

  • Hi Scott,



    I have a methods which takes UserID of the logged in user as an argument.Is there any way I can get access to profile's UserID without running a query on aspnet_users table??



    Thanks

    Rushi

  • Just to follow up on Josh's comment, you can also then write:



    ProfileInfoCollection pc = ProfileManager.FindProfilesByUserName(ProfileAuthenticationOption.All, "nameprefix%");



    foreach (ProfileInfo pi in pc) {



    }



    To iterate over the profileInfo objects based on a name query you provide. Within the foreach you should be able to use the code that Josh provided above to lookup the profile and add it to a collection that you then databind against.



    Hope this helps,



    Scott

  • Hi Rushi,



    You can access the User.Identity.Name property on a page (or via HttpContext) to get access to the logged in user's UserID. This obtains the information for the security context (example: FormsAuthentication ticket or Windows identity token) -- so doesn't need to hit the aspnet_users table.



    Hope this helps,



    Scott

  • Almost there. Once I have a ProfileInfo object - how can I get access to the custom profile information (specified in web.config?)

  • Hi Bela,

    The ProfileInfo object exposes the UserName property, which you can use to get a ProfileCommon object, using Profile.GetProfile(username). Your ProfileCommon object then exposes your custom properties you set in your web.config. Try something like this...



    //c#

    ProfileInfoCollection pc = ProfileManager.GetAllProfiles(ProfileAuthenticationOption.All);

    foreach (ProfileInfo pi in pc) {

    ProfileCommon prof = Profile.GetProfile(pi.UserName);

    }



    'vb

    Dim pc As ProfileInfoCollection = ProfileManager.GetAllProfiles(ProfileAuthenticationOption.All)

           For Each pi As ProfileInfo In pc

               Dim prof As ProfileCommon = Profile.GetProfile(pi.UserName)

               'get your values from prof

           Next



    Regards,

    Justin

  • scottgu
    I assume your'e talking about the default provider when you say "The profile data is actually only ever loaded when someone tries to access the profile properties." and that it uses a lazy-load pattern.
    If I'm right, the default provider is that of type 'System.Web.Profile.SqlProfileProvider'.
    When looking through the sourcecode for that class I cannot seem to find any traces of that lazy-load mechanism...

    If I were to implement a custom provider, how would I go about and implement such a mechanism. I assume that the property IsDirty would be used in some way.

    Best regards,
    Richard

  • Hi Richard,

    The lazy-loading actually happens via the Profile API when it loads the provider. Basically it doesn't call the ProfileProvider until someone tries to access one of the Profile API's properties. That way you don't need to-do anything special within your provider to get this behavior.

    Hope this helps,

    Scott

  • hi everyone,

    I am planning to use profile info to store Table/Record Authorization of the user. After reading all your comments and investigating profile class I am not sure to with profile anymore. An sql table to store the recordbase authorization might be easier. Do you have any comment on this subject?

  • Hi Sarp,

    One option you can look at is to map the Profile API against a SQL table or SPROC directly. This provider enables this support pretty easily: http://weblogs.asp.net/scottgu/archive/2006/01/10/435038.aspx

    Hope this helps,

    Scott

  • Is there a way to just get the guid id for the user from the membership provider or the profile provider, without having to do a select on the user table.

    Vince

  • Hi Vince,

    There is no way to get the GUID without hitting the table. However, you could use the username as the access key -- this is cached from the forms-auth cookie and so is super efficient to access.

    Alternatively, you could retrieve the GUID once and then cache it within the private security storage section of the FormsAuthentication ticket. This will encrypt and stick it in the forms-auth cookie as well, and allows you to avoid hitting the database on subsequent requests.

    Hope this helps,

    Scott

  • Hi Sam,

    Yep -- you can get access to the UserID column value through that property on the MembershipUser object returned from Membership.GetUser().

    In general, I'd probably still recommend that you use the username (as a string) value as your keys elsewhere -- since that will enable you to change your membership storage implementation at a later date (for example: store in another database or within active directory) wihtout you having to worry about dependencies you might have on the origional GUID value.

    Hope this helps,

    Scott

  • Hi Sam,

    One approach to take would be to never delete users, but just mark them as inactive (the Membership API supports this). That way you never need to worry about adding a duplicate user to the system.

    Hope this helps,

    Scott

  • okay I figured out solution to my own problem. I assigned a value to a placeholder profile field, call Save() -> UserName is populated with the UserId Guid.

  • Hi. Maybe somebody could help me. Everytime I start application both SetPropertyValues and GetPropertyValues fired. But SetPropertyValues fired out-side of my application and I never call Profile.Save method. Maybe somebody could help me in this or had the same behaviour?

    Regards, Valentyn.

    Plase, diblicate your answer to bootloader@lit.ru

  • Hi Parus,

    That is very odd. Can you set a breakpoint on your provider to see what the call-stack of the caller is?

    Thanks,

    Scott

  • is there a way to access profile in web custom control???

    i created some property in web.config,, and i would like to access those value in a web custom control..

  • i created some custom properties in web.config,, how can i access those properties in web custom control??? can any one help me...

  • Hi Scorpian,

    You can write the below code to get access to a late-bound Profile object:

    HttpContext context;
    context = HttpContext.Current;

    context.Profile

    There are then get/set methods on this context.Profile object that you can use within your custom control.

    Hope this helps,

    Scott

  • Hi Scott,

    Thanks for the tip, but it wasn't the answer i was looking for.

    I just wanted to know the reasons behind your recommendation of using UserName as the FK instead of UserId. As I mention in my last post, it seems very difficult to get the UserId with hitting the database with membership.GetUser() whereas UserName is easily available from Context.User.UserName.

    Hope its more clear this time.

    thanks heaps Scott!

    Anthony

  • Hi Anthony,

    You can retrieve a userkey from the membership provider by writing code like this:

    MembershipUser user = Membership.GetUser("username");
    object userKey = user.ProviderUserKey;

    This enables a Membership provider to surface the primary key they are using to store the user. In the case of the default SQLMembershipProvider that ships with ASP.NET 2.0 this is a GUID value.

    Hope this helps,

    Scott

  • Hi Scott,

    Sorry to drag this on, but one last question.

    If I had a User intensive website, where most of the CRUD requires the use of an UserId parameter.
    Now, what would be the best option?
    1. Call Membership.GetUser("Username") just before each CRUD inside each Page?
    2. Get my SP to lookup the userId given the username and applicationId
    3. store the UserId inside the UserData field in the cookie?
    4. Use username as the FK in all my tables.
    5. Something better than the above?

    thanks

    Anthony

  • Hi Anthony,

    Sorry for the delay in getting back to you on this!

    Any chance you could send me email on this topic (scottgu@microsoft.com)? That way we can continue to conversation and I can also help loop in a few other folks to get their advice.

    Thanks,

    Scott

  • Hi Scott,

    How does the profile system handle visits from crawlers like googlebot? Since it obviously can't write a persistent cookie does that mean a new GUID is generated for each request?

    Thanks,
    Martin

  • Is there a way to lookup profiles other than by using username (FindProfilesByUserName)? For instance, I have a page where I would like to show all users from a certain state. I'd hate to have to call GetAllProfiles and filter out the ones not in the state I'm interested in. This could take a long time if the site has a lot of users.

  • Hi Martin,

    If you are using authenticated profiles (the default), then you only issue a profile when a user logs in (and since bots don't login you never issues a profile cookie).

    With anonymous profiles they'll be issues a cookie - although since they never store anything on the server it won't persist anything in the profile store.

    Hope this helps,

    Scott

  • Hey Scott,

    Did you get my email from last week?
    Just wondering if it ever reached your inbox.

    thanks

    Anthony

  • Hi Scott,

    Little different issue here.
    I'm creating a custom profile provider for Oracle. I am unable to see the default/intrisic Profile object. i.e. it does not show up in intellisense.

    I've clean compiled, checked web.config profile declaration 100 times. I don't have a fully functional (it's stubbed) provider yet but it should show up.

    I've even tried defining the default sql profile provider in web.config and do not see the intrinsic Profile object.

    What must happen to make the Profile instance show up?

  • Hey Scott,

    I am trying to implement custom WCF membership and profile providers. All seems to be working as it should.

    However, we have opted to not use the default ASP.Net membership controls such as login, User Registration Wizard etc. This is due to an existing control framework in place.

    My problem seems to be that the default providers fire internal events, which I cannot reproduce.

    Example: the Membership.ValidateUser() method calls;

    WebBaseEvent.RaiseSystemEvent(null, 0xfa2, username);

    Could you provide any clarity on how I might handle LoggingIn, setting the HttpContext.User and triggering a MigrateAnonymousEvent?

    Many thanks

    Christian

  • Hi Christian,

    Any chance you could send me an email with details about this problem? I can then loop you in with some folks who can help provide an answer.

    Thx!

    Scott

    P.S. Have you also looked at the source code for the default ASP.NET Provider implementations: http://weblogs.asp.net/scottgu/archive/2006/04/13/Source-Code-for-the-Built_2D00_in-ASP.NET-2.0-Providers-Now-Available-for-Download.aspx

  • am relatively new to the asp.net 2.0 frame. I am using the role,membership and profile model. The backend for the application is a Sql Sever 2005 database. While the roles and membership work as intended , I am unable to use Profile. For one the 'Profile' class does not show up in the intellisense. I always get the error :
    'The name 'Profile' does not exist in the current context '

    On the back end , i can see the aspnet_Profile table has been created.
    Intially when i used the aspnet_regsql.exe tool I only utilized the 'm' and 'r' options (membership and roles). I didn't need to store addtional user specific information. However the requirements changed and I now need to add user-personalization data so i thought using Profiles would be the way to go ( it seemed to take a lot less time than creating my custom tables).So I then ran the aspnet_regsql.exe tool, but this time only with the 'p' option(Profile). Could that be the reason why it isn't working.
    This is what my web.config looks like:




    ..................






    ..............





    ......................................
    ......................................









































    configuration>

  • I am trying to use Profiles, but i keep getting the error:
    The name Profile does not exist in the current context

  • Hi Rachel,

    I believe you want to-do this instead:

    ProfileCommon userProfile = (ProfileCommon) Profile.Create("UserName");

    userProfile.TestProperty = "Hello World";
    userProfile.Save();

    Note that you'll need to use the "Save()" method at the end to save the profile changes - since you are creating a custom profile instance the page won't do it for you.

    Hope this helps,

    Scott

  • If you want to access a particular profile property (that you've set in web.config) from outside the ASP.NET scope of ProfileCommon you need to use ProfileBase.Create(). Of course, you lose strong typing, etc.

    // given a MembershipUser user
    ProfileBase pb = ProfileBase.Create(user.UserName);
    object pvalue = pb.GetPropertyValue["yourpropertyname"];

Comments have been disabled for this content.