Copied to clipboard

Flag this post as spam?

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


  • Johan 6 posts 86 karma points
    Oct 31, 2019 @ 10:05
    Johan
    0

    Custom membership provider in Umbraco 8

    Hello Umbracoland

    I want to move my members from the umbraco database to another database, where the members will be stored. I need to implement my own membership provider, as I want to hash everything we know about our users.

    Untill now I have just been trying to very simple membership provider to store some mock users in a local database. I have so far based my solution on an earlier post (https://our.umbraco.com/forum/developers/extending-umbraco/74219-custom-membership-provider/), however I am using the Entity framework instead.

    So far I have

    • Created a custom membership provider inheriting from the standard membership provider.
    • Made a member repository with methods for interactions with the database.
    • Made a model class with an entity framework class.
    • Replaced the default umbraco membership provider with my custom membership provider in the Web.config file.

    When I try to create a member in the backoffice -> Members -> Members -> create I get an error message. To me it seems that Umbraco doesn't recognize my membership provider. I hope someone out there is able to helpt me, I've been stuck with this for quite some time now.

    Error message

    System.NullReferenceException: Object reference not set to an instance of an object.

    Stacktrace

    at Umbraco.Web.Models.Mapping.MemberTabsAndPropertiesMapper.Map(IMember source, MapperContext context) at Umbraco.Web.Models.Mapping.MemberMapDefinition.Map(IMember source, MemberDisplay target, MapperContext context) at Umbraco.Core.Mapping.UmbracoMapper.<>c_DisplayClass802.<Define>b__1(Object source, Object target, MapperContext context) at Umbraco.Core.Mapping.UmbracoMapper.Map[TTarget](Object source, Type sourceType, MapperContext context) at Umbraco.Core.Mapping.UmbracoMapper.Map[TTarget](Object source, MapperContext context) at Umbraco.Web.Editors.MemberController.GetEmpty(String contentTypeAlias) at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass6_2.<GetExecutor>b__2(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary2 arguments, CancellationToken cancellationToken)

    My code

    CustomMemberhipProvider.cs

    public class CustomMembershipProvider : MembershipProvider
    {
        private string _applicationName = "UmbracoMembershipProvider";
    
        public override string ApplicationName {
            get { return _applicationName; }
            set
            {
                if (string.IsNullOrEmpty(value))
                    throw new ProviderException("ApplicationName cannot be empty");
                if (value.Length > 0x100)
                    throw new ProviderException("Provider application name too long");
                _applicationName = value;
            }
        }
      public override void Initialize(string name, NameValueCollection config)
        {
            base.Initialize(name, config);
        }
    
    
        public override bool EnablePasswordRetrieval => false;
    
        public override bool EnablePasswordReset => false;
    
        public override bool RequiresQuestionAndAnswer => false;
    
        public override int MaxInvalidPasswordAttempts => throw new NotImplementedException();
    
        public override int PasswordAttemptWindow => throw new NotImplementedException();
    
        public override bool RequiresUniqueEmail => true;
    
        public override MembershipPasswordFormat PasswordFormat => MembershipPasswordFormat.Hashed;
    
        public override int MinRequiredPasswordLength => 6;
    
        public override int MinRequiredNonAlphanumericCharacters => 0;
    
        public override string PasswordStrengthRegularExpression => throw new NotImplementedException();
    
        public override bool ChangePassword(string username, string oldPassword, string newPassword)
        {
            throw new NotImplementedException();
        }
    
        public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
        {
            throw new NotImplementedException();
        }
    
        public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
        {
            var memberRepository = new MembersRepository();
            bool memberCreated = memberRepository.CreateUser(username, email, password);
                MembershipUser newMember = new MembershipUser(
                "UmbracoMembershipProvider",
                username,
                providerUserKey,
                email,
                passwordQuestion,
                "",
                isApproved,
                false,
                DateTime.Now,
                DateTime.Now,
                DateTime.Now,
                DateTime.Now,
                DateTime.Now
                );
            if( memberCreated)
            {
                status = MembershipCreateStatus.Success;
                return newMember;
    
            }
            status = MembershipCreateStatus.ProviderError;
            return null;
        }
    
        public override bool DeleteUser(string username, bool deleteAllRelatedData)
        {
            var memberRepository = new MembersRepository();
            return memberRepository.DeleteUser(username);
        }
    
        public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            throw new NotImplementedException();
        }
    
        public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            throw new NotImplementedException();   
        }
    
        public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
        {
            throw new NotImplementedException();
        }
    
        public override int GetNumberOfUsersOnline()
        {
            throw new NotImplementedException();
        }
    
        public override string GetPassword(string username, string answer)
        {
            throw new NotImplementedException();
        }
    
        public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
        {
            var repos = new MembersRepository();
            MockUserClass member = repos.GetUserById( (Guid)providerUserKey );
            if (member != null)
                return ConvertToMembershipUser(member);
            return null;
        }
    
        public override MembershipUser GetUser(string username, bool userIsOnline)
        {
            var repos = new MembersRepository();
            var member = repos.GetUserByName(username);
            if (member != null)
            {
                return ConvertToMembershipUser(member);
            }
            return null;
        }
    
        public override string GetUserNameByEmail(string email)
        {
            var repos = new MembersRepository();
            return repos.GetUserNameByEmail(email);
        }
    
        public override string ResetPassword(string username, string answer)
        {
            throw new NotImplementedException();
        }
    
        public override bool UnlockUser(string userName)
        {
            throw new NotImplementedException();
        }
    
        public override void UpdateUser(MembershipUser user)
        {
            throw new NotImplementedException();
        }
    
        public override bool ValidateUser(string username, string password)
        {
            var repos = new MembersRepository();
            MockUserClass member = repos.GetUserByName(username);
            if(member != null)
            {
                if (member.Password == password)
                    return true;
            }
            return false;
        }
    
        private MembershipUser ConvertToMembershipUser(MockUserClass member)
        {
            return new MembershipUser("UmbracoMembershipProvider", member.Username, member.Id, member.Email, "", "", member.IsApproved, member.IsLockedOut, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.MinValue, DateTime.MinValue);
        }
    
        private MembershipUserCollection GetMembershipUserCollection(IEnumerable<MockUserClass> queryResult)
        {
            var Members = new MembershipUserCollection();
            foreach (var member in queryResult)
            {
                Members.Add(ConvertToMembershipUser(member));
            }
            return Members;
        }
    }
    

    MembersRepository.cs

    public class MembersRepository
    {
    
        public bool CreateUser(string username,string email, string password)
        {
            using (var context = new UserDb())
            {
                var newMember = new MockUserClass(
                username,
                password,
                email
                );
                context.Members.Add(newMember);
                return true;
            };
    
        }
    
        public bool DeleteUser(string username)
        {
            using (var context = new UserDb())
            {
                var member = (from m in context.Members
                              where m.Username == username
                              select m).FirstOrDefault();
                if (member != null)
                {
                    context.Members.Remove(member);
                    return true;
                }
                return false;
            }
    
        }
        public MockUserClass GetUserById(Guid id)
        {
            using (var context = new UserDb())
            {
                var member = (from m in context.Members
                              where m.Id == id
                              select m).FirstOrDefault();
                return member;
            }
        }
        public MockUserClass GetUserByName(string name)
        {
            using (var context = new UserDb())
            {
                var member = (from m in context.Members
                              where m.Username == name
                              select m).FirstOrDefault();
                return member;
            }
        }
    
        public string GetUserNameByEmail(string email)
        {
            using (var context = new UserDb())
            {
                var username = (from member in context.Members
                                where member.Email == email
                                select member.Username).FirstOrDefault();
                return username;
            }
        }
    }
    

    Entity framework class

    public class UserDb : DbContext
    {
        public UserDb():base("name=UserDb"){}
        public DbSet<MockUserClass> Members { get; set; }
    }
    

    Snippets from web.config

    <connectionStrings>
    <remove name="umbracoDbDSN" />
    // umbraco database connection, removed for clarity
    <add name="UserDb" connectionString="Data Source=PF1PXX7N\SQLEXPRESS;Initial Catalog=MockUserDatabase;Integrated Security=True" providerName="System.Data.SqlClient" />
    

    <providers>
        <clear />
        <add name="UmbracoMembershipProvider" type="UserProject.Classes.CustomMembershipProvider, UserProject" minRequiredNonalphanumericCharacters="0" minRequiredPasswordLength="8" useLegacyEncoding="true" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" defaultMemberTypeAlias="Member" passwordFormat="Hashed"/>
        <add name="UsersMembershipProvider" type="Umbraco.Web.Security.Providers.UsersMembershipProvider, Umbraco.Web" />
      </providers>
    </membership>
    
  • Ian 178 posts 752 karma points
    Nov 04, 2019 @ 14:14
    Ian
    100

    Hi Johan what does your MockUserClass look like? Does it implement the IMember interface which the Umbraco mapper looks to be expecting?

  • Johan 6 posts 86 karma points
    Nov 04, 2019 @ 14:55
    Johan
    0

    Hi Ian

    No it does not! I will try to implement it and return with a result.

  • Johan 6 posts 86 karma points
    Nov 04, 2019 @ 15:26
    Johan
    0

    I think this has solved my problem, now I just need to figure out what to implement! thank you so much!

  • Ion Cracea 12 posts 93 karma points
    Mar 06, 2020 @ 16:44
    Ion Cracea
    0

    Hi, do you still remember how exactly you solved the problem? I.ve implemented the IMember interface but that hasn't worked anyway. An example code would be much appreciated. Thank you.

  • Jay 416 posts 642 karma points
    Jun 29, 2023 @ 10:48
    Jay
    0

    I am looking to do something similar. Appreciate if there's any sharing on this. thanks

Please Sign in or register to post replies

Write your reply to:

Draft