4

I am building a custom MembershipProvider more precisely the GetUser function.

Therefor i have a custom MembershipUser.

public class CustomMemberShipUser : MembershipUser
{
    public CustomMemberShipUser (
        string providerName,
        string email,
        object providerUserKey,
        string name,
        string passwordQuestion,
        string comment,
        bool isApproved,
        bool isLockedOut,
        DateTime creationDate,
        DateTime lastLoginDate,
        DateTime lastActivityDate,
        DateTime lastPasswordChangedDate,
        DateTime lastLockoutDate
        ): base(
            providerName, email, providerUserKey, name, passwordQuestion,
            comment, isApproved, isLockedOut, creationDate, lastLoginDate,
            lastActivityDate, lastPasswordChangedDate, lastLockoutDate)
    {
    }
}

In the GetUser function of the MembershipProvider i get the user data and put them into the CustomMemberShipUser.

public override MembershipUser GetUser(string email, bool userIsOnline)
    {
        User u = _db.Users.Where(x => x.Email == email).First();
        CustomMemberShipUser customUser = new CustomMemberShipUser (
                                        "CustomMemberShipUser ",
                                        u.Email, 
                                        u.id,
                                        u.Email, 
                                        "", 
                                        "", 
                                        true, 
                                        false, 
                                        u.CreateDate, 
                                        DateTime.MinValue, 
                                        DateTime.MinValue, 
                                        DateTime.MinValue, 
                                        DateTime.MinValue);
        return customUser ;
    }

As you can see i use the email as name for the MemberShip and i don't need most of the other parameters.

Is there a way to make the call simpler? I don't want to initalize the MembershipUser with empty Strings and minimal Date values.

Thanks in advance

r3d
  • 85
  • 10
  • I don't think you can avoid it. however you can make your constructor take less arguments – Eranga Jun 10 '11 at 07:06
  • If your are using SQL-Server as DBMS and the standard ASP.Net DB-Schema, you could let your custom MembershipProvider inherit from [SqlMembershipProvider](http://msdn.microsoft.com/en-us/library/system.web.security.sqlmembershipprovider.aspx). SqlMembershipProvider has a [public constructor without parameters](http://msdn.microsoft.com/en-us/library/system.web.security.sqlmembershipprovider.sqlmembershipprovider%28v=vs.80%29.aspx#1). – Tim Schmelter Jun 10 '11 at 07:20
  • @Tim hes trying to use a Custom Membership Provider. if you had parameters in your Membership constructor how can Asp.net runtime instantiate it? – Eranga Jun 10 '11 at 07:25
  • thanks for the fast answers. The Problem is in the GetUser Function which have to return a MembershipUser and this constructor takes to much arguments. I have an own user entity which i want to use for the account handling and not the build in user object. So i don't need the parameters. Is there any chance to get this done? – r3d Jun 10 '11 at 07:30
  • There is a protected ctor of MembershipUser that takes no parameters, but then you cannot set the provider name anymore. So I think you have to use this other ctor... – Tz_ Jun 10 '11 at 08:20

1 Answers1

4

Could you adapt your CustomMembershipUser to do the 'padding' for you

   public class CustomMemberShipUser : MembershipUser
    {
        public CustomMemberShipUser (
            string email,
            object providerUserKey,
            ): base(
                "CustomMemberShipUser", email, providerUserKey, email, String.Empty,
                String.Empty, true, false, DateTime.MinValue, DateTime.MinValue,
                DateTime.MinValue, DateTime.MinValue, DateTime.MinValue)
        {
        }
    }

It doesn't solve the problem but it will tidy up your provider which will become

public override MembershipUser GetUser(string email, bool userIsOnline)
    {
        User u = _db.Users.Where(x => x.Email == email).First();
        CustomMemberShipUser customUser = new CustomMemberShipUser (u.Email, u.id);
        return customUser ;
    }

I presume your CustomMembershipUser is exposing some additional properties that you are not showing us. As it stands you could just return a MembershipUser. With the above the only benefit your CustomMembershipUser gives you is the cleaner construction in your CustomMembershipProvider

NinjaNye
  • 7,046
  • 1
  • 32
  • 46
  • thanks for your answer, atm i don't use other additional properties. I only use a custom entity for the authentification and i want to map this to the MembershipUser, so i can use [Authenticate]. Is this the right way to do this or is there a better solution? – r3d Jun 10 '11 at 09:01
  • In that case you can scrap your CustomMembershipUser class and use the [Authorize] attribute to ensure a user is logged in before they access your pages. In terms of authenticating a login request you should override ValidateUser in your MembershipProvider class with your logic for checking password etc – NinjaNye Jun 10 '11 at 09:15
  • This might be worth a look: http://theintegrity.co.uk/2010/11/asp-net-mvc-2-custom-membership-provider-tutorial-part-1/ – NinjaNye Jun 10 '11 at 09:21
  • yes, for authentication i already used the ValidateUser function. But i need the CustomMemberShipUser when i need the ChangePassword function. Would it be better not to override the changePassword function in the MembershipProvider but write an extra one? – r3d Jun 10 '11 at 09:54
  • Override the existing ChangePassword method, providing you have updated your .webconfig file to use your CustomMemberhipProvider it will all work nicely. You don't require a CustomMembershipUser for this. – NinjaNye Jun 10 '11 at 10:17
  • to change the password i have to call MemberShip.GetUser(name); and this method returns a MemberShipUser. Therfor i use the CustomMembershipUser because i don't need all the parameters. I will finally use your suggestions above to make the call simple. – r3d Jun 10 '11 at 10:27
  • No, you should get the user from your userRepository, or dataContext if you don't have repositories, perform your checks against the old password, if they match, set the new password, and return success/failure – NinjaNye Jun 10 '11 at 10:35
  • Just seen your edit. You could indeed still use the CustomMembershipUser to simplify the call – NinjaNye Jun 10 '11 at 10:38
  • can you explain a userRepository in more detail? In the AccountController of a default MVC Internet Applicaton there is an Action called ChangePassword. MembershipUser currentUser = Membership.GetUser(User.Identity.Name); changePasswordSucceeded = currentUser.ChangePassword(model.OldPassword, model.NewPassword); How should i change this call to get it done? – r3d Jun 10 '11 at 10:42
  • A repository is a layer of abstraction that sits between your code and your dataContext. If you don't have repositories then you can use your datacontext and get the user that way. To answer your question you don't need to change anything in the account controller. The account controller calls MembershipUser.ChangePassword which in turn will call MembershipProvider.ChangePassword. – NinjaNye Jun 10 '11 at 10:57
  • BTW You should find a good repository pattern tutorial here: http://stackoverflow.com/questions/3175/repository-pattern-tutorial-in-c – NinjaNye Jun 10 '11 at 10:58