Accessing custom profile field in module after create

Accessing custom profile field in module after create

This question is answered

Hi

We are trying to set user profile CommonName property on registration. I have a CSModule that hooks the PostUserUpdate event. However I've not had any joy in accessing our custom profile fields "FirstName" and "LastName" that are displayed on the registration form. Doing the following returns an empty string:

var profileService = Services.Get<IUserProfileService>();
UserProfileDataBase profileData = profileService.GetProfileData(user);

string realName = string.Concat(
  profileData.GetStringValue("FirstName", ""),
   " ",
  profileData.GetStringValue("LastName", "")
);

Any suggestions?
Many thanks.

Verified Answer
  • bump.

  • Arol. If I remember rightly custom profile fields are not set until after the user has been created. Perhaps try monitoring the PostUserUpdate event instead.

    Also just out of interest how have you added these custom fields, with a custom version of the widget/reg form with code or just by configuring the the reg widget using the widget config options in edit mode?

    To double check I would recommend trying to call the rest api getuser() method to see if the Firstname and Lastname fields are actually being set.

    hope this helps

  • Thanks Adam - in fact, I was bumping it for Nigel, who I work with. I'm completely non-technical myself!

  • The problem here is that profiles are saved separately to the user, and the PostUserUpdate event on user creation is fired before the profile is saved.  To react to profile data, you need to use the PostUserProfileDataUpdate event, and then if the concatanation of FirstName and LastName is not equal to the user's Display Name, then update the user's display name.

  • Thanks for the suggestions. Alex, I can certainly see the profile data in that event, which is a step in the right direction. However, trying to save the real name into the CommonName doesn't have much effect. Can you spot an issue with this:

    private void csa_PostUserProfileDataUpdate(UserProfileDataBase p, CSEventArgs e)
            {

                if (e.State == CommunityServer.Components.ObjectState.Update)
                {
                    User user = CommunityServer.Users.GetUser(p.UserID);
                    string name = string.Concat(p.GetStringValue("FirstName", ""), " ", p.GetStringValue("LastName", "")).Trim();

                    if (!string.IsNullOrEmpty(name) && !user.Profile.CommonName.Equals(name, StringComparison.OrdinalIgnoreCase))
                    {

                        user.Profile.CommonName = name;
                        if (!Globals.IsNullorEmpty(user.Profile.CommonName) && user.Profile.CommonName.Length > 50)
                        {
                            user.Profile.CommonName = user.Profile.CommonName.Substring(0, 50);
                        }
                        user.Profile.CommonName = Globals.EnsureHtmlEncoded(user.Profile.CommonName);
                        user.Profile.Save();
                    }
                }
            }

    Also, we really only want to set this on registration and allow the user to override the common name later on if they choose. The ObjectState - in debugging - is never Create. Is there some other piece of the puzzle I may be missing?

    Thanks!

  • You should use the PreUserProfileDataUpdate event - that way you don't need to explicitly save the profile to the database as you've modified the profile BEFORE the profile is saved to the database (as opposed to AFTER when using hte POSTUserProfileDataUpdate event).  

    As for the profile being in the Create update state, Profiles only ever get updated (or deleted).  You need to use some method to determine the first time a profile gets updated.  A few ways to consider for doing this.

    * Stick an object into HTTPContext.Current.Items when a user is created.  This object will only exist for the lifetime of the request when the user is created

    * Check the created date of the user and see if it was within the last 10 seconds.

    * Create a custom profile field "hasUpdatedDisplayName" and use that to determine whether you have updated the user's display name yet.

  • Alex,

    I had already tried PreUserProfileDataUpdate without success, CommonName was just not being updated. I have managed to get this working finally using a combination of PreUserUpdate and PostUserUpdate events and your suggestion of putting an object in Context.

    It seems the PreUserUpdate fires twice on registration, I assume once for creating the user and a second time when the profile is updated. Setting a value in Context on PostUserUpdate and looking for that in PreUserUpdate with an ObjectState.Update, I can then access the custom profile fields which are now set using the IUserProfileService and assign to Profile.CommonName.

    Got there in the end! Thanks for your assistance.

All Replies
  • bump.

  • Arol. If I remember rightly custom profile fields are not set until after the user has been created. Perhaps try monitoring the PostUserUpdate event instead.

    Also just out of interest how have you added these custom fields, with a custom version of the widget/reg form with code or just by configuring the the reg widget using the widget config options in edit mode?

    To double check I would recommend trying to call the rest api getuser() method to see if the Firstname and Lastname fields are actually being set.

    hope this helps

  • Thanks Adam - in fact, I was bumping it for Nigel, who I work with. I'm completely non-technical myself!

  • The problem here is that profiles are saved separately to the user, and the PostUserUpdate event on user creation is fired before the profile is saved.  To react to profile data, you need to use the PostUserProfileDataUpdate event, and then if the concatanation of FirstName and LastName is not equal to the user's Display Name, then update the user's display name.

  • Thanks for the suggestions. Alex, I can certainly see the profile data in that event, which is a step in the right direction. However, trying to save the real name into the CommonName doesn't have much effect. Can you spot an issue with this:

    private void csa_PostUserProfileDataUpdate(UserProfileDataBase p, CSEventArgs e)
            {

                if (e.State == CommunityServer.Components.ObjectState.Update)
                {
                    User user = CommunityServer.Users.GetUser(p.UserID);
                    string name = string.Concat(p.GetStringValue("FirstName", ""), " ", p.GetStringValue("LastName", "")).Trim();

                    if (!string.IsNullOrEmpty(name) && !user.Profile.CommonName.Equals(name, StringComparison.OrdinalIgnoreCase))
                    {

                        user.Profile.CommonName = name;
                        if (!Globals.IsNullorEmpty(user.Profile.CommonName) && user.Profile.CommonName.Length > 50)
                        {
                            user.Profile.CommonName = user.Profile.CommonName.Substring(0, 50);
                        }
                        user.Profile.CommonName = Globals.EnsureHtmlEncoded(user.Profile.CommonName);
                        user.Profile.Save();
                    }
                }
            }

    Also, we really only want to set this on registration and allow the user to override the common name later on if they choose. The ObjectState - in debugging - is never Create. Is there some other piece of the puzzle I may be missing?

    Thanks!

  • You should use the PreUserProfileDataUpdate event - that way you don't need to explicitly save the profile to the database as you've modified the profile BEFORE the profile is saved to the database (as opposed to AFTER when using hte POSTUserProfileDataUpdate event).  

    As for the profile being in the Create update state, Profiles only ever get updated (or deleted).  You need to use some method to determine the first time a profile gets updated.  A few ways to consider for doing this.

    * Stick an object into HTTPContext.Current.Items when a user is created.  This object will only exist for the lifetime of the request when the user is created

    * Check the created date of the user and see if it was within the last 10 seconds.

    * Create a custom profile field "hasUpdatedDisplayName" and use that to determine whether you have updated the user's display name yet.

  • Alex,

    I had already tried PreUserProfileDataUpdate without success, CommonName was just not being updated. I have managed to get this working finally using a combination of PreUserUpdate and PostUserUpdate events and your suggestion of putting an object in Context.

    It seems the PreUserUpdate fires twice on registration, I assume once for creating the user and a second time when the profile is updated. Setting a value in Context on PostUserUpdate and looking for that in PreUserUpdate with an ObjectState.Update, I can then access the custom profile fields which are now set using the IUserProfileService and assign to Profile.CommonName.

    Got there in the end! Thanks for your assistance.