Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Robert Mulder 79 posts 269 karma points c-trib
    Jul 28, 2014 @ 16:37
    Robert Mulder
    0

    Get actual name of member

    I'm trying to send an e-mail to a newly created member using the new MemberService in 7.1 but I seem to be unable to find the actual name of the user (like many others it seems) and it doesn't seem like any of the 'similar topics' provides an answer.

    Here's what I do. In application startup I add a listener to the created event like so:

    MemberService.Created += MemberService_Created;
    

    And in MemberService_Created I have access to the newly created IMember

    void MemberService_Created(IMemberService sender, NewEventArgs<IMember> e) {
        try {
            var name = e.Entity.Name; // No it's not!!
            var email = e.Entity.Email;
            var username = e.Entity.Username;
            SomeHelper.SendEmail(name, email, username);
        } catch (Exception ex) {
            LogHelper.Error<ApplicationStartup>("Error sending new member email.", ex);
        }
    }
    

    Unfortunately in the code sample above the name variable is just the Username. I've looked at all the properties of the IMember but there is none that contains the value I've entered as the name of the user when creating it in the Umbraco backend.

    Am I completely missing something or is there just no easy way to get to the user name from the Created event?

  • Sebastiaan Janssen 4876 posts 14511 karma points MVP admin hq
    Jul 28, 2014 @ 19:24
    Sebastiaan Janssen
    0

    Try e.Entity.Text.

  • Robert Mulder 79 posts 269 karma points c-trib
    Jul 28, 2014 @ 19:51
    Robert Mulder
    0

    Alas, there is no Text property on IMember. Also tried new Member(id) which does have a .Text property, but it also contains the username, not the node name.

  • Sebastiaan Janssen 4876 posts 14511 karma points MVP admin hq
    Jul 28, 2014 @ 19:51
    Sebastiaan Janssen
    0

    Interestingly, you're right, it seems like we don't expose that information currently.. ouch!

    Looks like you can only get it from the obsoleted API.. :(

    var m = umbraco.cms.businesslogic.member.Member.GetMemberFromLoginName(e.Entity.Username);
    var name = m.Text;
    
  • Sebastiaan Janssen 4876 posts 14511 karma points MVP admin hq
    Jul 28, 2014 @ 19:55
    Sebastiaan Janssen
    0

    Not sure yet how we're going to fix this one, hope Shannon comes up with a good one: http://issues.umbraco.org/issue/U4-5287

  • Robert Mulder 79 posts 269 karma points c-trib
    Jul 28, 2014 @ 19:55
    Robert Mulder
    0

    Hmm, I thought that was the object you'd get when using the new Member(id) syntax, which I'm sure gives the username as result instead of the node name.

  • Sebastiaan Janssen 4876 posts 14511 karma points MVP admin hq
    Jul 28, 2014 @ 19:56
    Sebastiaan Janssen
    0

    Depends on your usings.. :) That's why I included the complete old namespace.

  • Robert Mulder 79 posts 269 karma points c-trib
    Jul 28, 2014 @ 19:58
    Robert Mulder
    0

    I thought I used that one, but it's off the top of my head, those namespaces all look alike. I'll take a look tomorrow and see. Otherwise it's a good opportunity to try those panic trousers ;)

  • Shannon Deminick 1494 posts 5053 karma points hq
    Jul 29, 2014 @ 04:38
    Shannon Deminick
    0

    Hi,

    I've added these two tests here that work:

    https://github.com/umbraco/Umbraco-CMS/commit/b5f900e789fb2e40cc166e5eee56e84f717b2319

    So here's what we need to know:

    • What action is creating the member that you are seeing their username as their 'Name'? (i.e. is it the creation of the member in the back office, via a front-end script, etc... ?) In lots of cases if a member signs up, their username will by default be their name.

    Here's a side bit of information that you need to know:

    I will update the documentation to reflect all of this accurately

  • Shannon Deminick 1494 posts 5053 karma points hq
    Jul 29, 2014 @ 05:32
    Shannon Deminick
    0

    Ok i can replicate this logic, here's what is happening

    • When the member is first created, it uses the membership provider to first create the member - this is required to support non-umbraco membership providers of course
      • Because a the Umbraco membership is active by default, this uses the UmbracoMembershipProvider which wraps the IMemberService. A membership provider has no notion of a 'real name', so it uses the login name when calling into the IMemberService.CreateMemberWithIdentity (which is the method that executes the 'Created' event)
      • After the initial creation of the member with the membership provider, we then check if the membership provider is an Umbraco membership provider, if so, then we lookup the raw IMember, set it's name value and save it using the IMemberService.Save method - which will also trigger an event.

    So the first thing you want to do is stop using the Created event as noted previously since you'll only want to send an email to members that have actually been persisted to the database.

    You'll then want to use the Saved event, but since the member has already been saved with an identity, you won't simply just be able to check if the member is new based on it's ID or the extension method mentioned in the doc link I sent above. Instead you should track who you've sent the email to, maybe even a custom property on the member itself. In that case, you'd want to subscribe to the 'Saving', ensure that the entity is not new (already has an identity), ensure you custom flag has not been set, then set your custom flag to true, send the email (recommended to do that async) and the member will then be persisted with your sent flag set.

    Moving forward, in the core we can look at calling a custom overloaded method on the Umbraco membership provider that also accepts a Name value, then check if an Umbraco membership provider is active and call that method, which would in turn call the CreateWithIdentity with the real name value. The reason this is not done now was because this is how the legacy membership stuff worked and I couldn't break compatibility but I think there might be a way to get this working without breaking anything, we'll see.

  • Shannon Deminick 1494 posts 5053 karma points hq
    Jul 29, 2014 @ 20:01
    Shannon Deminick
    0

    Unfortunately I cannot make this change without introducing a breaking change in the API. I'd have to modify the abstract method PerformCreateUser in the class Umbraco.Core.Security.UmbracoMembershipProviderBase

    This might be an 'acceptable' breaking change since I highly doubt anyone is inheriting from this class apart from us, but that's just an assumption.

    In the meantime you'll probably have to use the work around as described above.

  • Simon Dingley 1412 posts 3272 karma points c-trib
    Apr 23, 2018 @ 10:51
    Simon Dingley
    0

    Sorry to drag this up again but the problem still exists and I want to confirm my understanding of the workaround is correct as I've implemented what I understood of this thread and the results are still the same.

    Should it actually be as follows?

    1. Add a new boolean property to the member type e.g. SendWelcomeEmail.
    2. Subscribe to the Member.Saving event & check the entity has no identity whilst setting the new SendWelcomeEmail property value to true.
    3. Subscribe to the Member.Saved event, check the new property and if true send the email and set the new property value to false thus allowing us access to the new member properties and disabling the flag for future so emails are not set again.

    Cheers, Simon

  • Simon Dingley 1412 posts 3272 karma points c-trib
    Apr 23, 2018 @ 14:46
    Simon Dingley
    1

    For anyone else that might be fighting with this, I finally have a solution with thanks to Shannon. The solution is on the issue on the tracker but for the benefit of those reading on here, the solution was as follows…

    In the MemberService.Saving event handler I am doing the following:

    if (!member.HasIdentity)
    {
        member.SetValue("MemberCreationStatus", MemberStatus.InitialCreate.ToString());
    }
    else if (member.GetValue<MemberStatus>("MemberCreationStatus").Equals(MemberStatus.InitialCreate))
    {
        if (member.Username.Equals(member.Name))
        {
            member.SetValue("MemberCreationStatus", MemberStatus.InitialProviderSave.ToString());
        }
        else
        {
            member.SetValue("MemberCreationStatus", MemberStatus.InitialServiceSave.ToString());
        }
    }
    

    And in the MemberService.Saved event I am doing the following:

    foreach (var member in e.SavedEntities)
    {
        // We can skip this iteration if the member has not yet been persisted or they have already received the email
        if (member.GetValue<MemberStatus>("MemberCreationStatus") .Equals(MemberStatus.PasswordGenerated)) continue;
    
        if (member.GetValue<MemberStatus>("MemberCreationStatus").Equals(MemberStatus.InitialServiceSave))
        {
            member.SetValue("MemberCreationStatus", MemberStatus.PasswordGenerated.ToString());
            memberSvc.Save(member, false);
    
            // Generate a new password that meets minimum requirements
            var password = Membership.GeneratePassword(
                Membership.MinRequiredPasswordLength,
                Membership.MinRequiredNonAlphanumericCharacters);
    
            // Save the password to persist it before we send the email
            memberSvc.SavePassword(member, password);
    
            // Send the member a welcome email with the initial password
            Members.SendWelcomeEmail(member, password);
        }
    }
    

    My Enum is quite simply:

    public enum MemberStatus
    {
        InitialCreate,
        InitialProviderSave,
        InitialServiceSave,
        PasswordGenerated
    }
    
  • Simon Dingley 1412 posts 3272 karma points c-trib
    Sep 19, 2018 @ 10:00
    Simon Dingley
    0

    I've had to return to this due to reports of the welcome emails not being sent still. The Member.Saving event handler has been modified as follows:

    if (!member.HasIdentity) // This will mean that the member isn't created yet
    {
        member.SetValue("MemberCreationStatus", MemberStatus.InitialCreate.ToString());
        sender.Save(member, false); // Without this the welcome emails are still not sent!
    }
    else if (member.GetValue<MemberStatus>("MemberCreationStatus").Equals(MemberStatus.InitialCreate))
    {
        // The member has been created, if the username and name are the same it has most likely been set by the provider
        if (member.Username.Equals(member.Name))
        {
            member.SetValue("MemberCreationStatus", MemberStatus.InitialProviderSave.ToString());
        }
        else
        {
            // We reach this stage when the user is manually created in the back office as editors don't use the email as the username
            member.SetValue("MemberCreationStatus", MemberStatus.InitialServiceSave.ToString());
        }
    }
    else if(member.GetValue<MemberStatus>("MemberCreationStatus").Equals(MemberStatus.InitialProviderSave))
    {
        // Finally, udpate the status to indicate the service has now saved the member
        member.SetValue("MemberCreationStatus", MemberStatus.InitialServiceSave.ToString());
    }
    

    It really is far more complicated than it should be and I hope this gets some attention soon. Hopefully, this helps someone else out and save them tearing their hair out trying to get it to work as I did.

Please Sign in or register to post replies

Write your reply to:

Draft