Click here to Skip to main content
13,737,461 members
Click here to Skip to main content
Add your own
alternative version


90 bookmarked
Posted 28 Jan 2010
Licenced CPOL

Custom Fluent Nhibernate Membership and Role Provider

, 12 Aug 2012
Rate this:
Please Sign up or sign in to vote.
Custom implementation of Microsoft Membership and Role provider using Fluent Nhibernate


The intent of this article is to provide an implementation of Microsoft’s Membership (and Role) provider using Fluent Nhibernate. Fluent Nhibernate offers a simplified implementation of Nhibernate without using the XML(hbm) mapping files. Click here for more information on Fluent NHibernate.

I am new to Fluent Nhibernate (and to Nhibernate for that matter) so if you find any glaring mistakes in the code, please let me know and I will try to fix those.


For background on Fluent hibernate, please read the Fluent NHibernate Wiki.


This application was developed using VS2008 and SQL server 2005 and the code is written in C#. This application should also work in VS2005 although I have not tested it in VS2005.


Microsoft’s Membership Provider provides an easy way to integrate user management in ASP.NET applications. However if you are not using MS-SQL server or don't want to deal with scores of tables and stored procedures that the default provides creates, you would have to provide a custom implementation of the provider to suit your needs.

This article explains a basic Fluent Nhibernate implementation of Membership and Role provider. We are going to implement a simplified provider that only uses a subset of tables that the actual provider is using which is sufficient for most of the applications.


In this implementation, I am using only three tables Users, Roles and UsersInRoles. The structure and definition of the tables is shown below:


Users” table has a listing of all the users in your system, and “Role” table has all the roles. “UsersInRoles” is a Many to Many table which has Users and roles associated. In Microsoft’s implementation of the provider, the primary keys are GUIDs, but in our case I have stuck with integers which sound simpler to me.

Database scripts are included as part of the source code.

Fluent NHibernate Implementation

If you are not familiar with Fluent Nhibernate, I would suggest going through the basic sample project to understand this section.This is how the Fluent NHibernate solution looks and some explanations follow:



Entities contain our business domain representation of the Users and Roles. Users has a constructor and methods for adding and removing the Roles. These methods also add/remove from the inverse relationships. Users hold a reference to the roles it has, a role holds reference to how many users are associated with the role. Utils.MinDate() is used here to set a default min date for the database (SQL server in this case).

public class Users
        public virtual int Id { get; private set; }
        public virtual string Username { get; set; }
        public virtual string ApplicationName { get; set; }
        public virtual string Email { get; set; }
        public virtual string Comment { get; set; }
        public virtual string Password { get; set; }
        public virtual string PasswordQuestion { get; set; }
        public virtual string PasswordAnswer { get; set; }
        public virtual bool  IsApproved { get; set; }
        public virtual DateTime LastActivityDate { get; set; }
        public virtual DateTime LastLoginDate { get; set; }
        public virtual DateTime LastPasswordChangedDate { get; set; }
        public virtual DateTime CreationDate { get; set; }
        public virtual bool IsOnLine { get; set; }
        public virtual bool IsLockedOut { get; set; }
        public virtual DateTime LastLockedOutDate { get; set; }
        public virtual int FailedPasswordAttemptCount { get; set; }
        public virtual int FailedPasswordAnswerAttemptCount { get; set; }
        public virtual DateTime FailedPasswordAttemptWindowStart { get; set; }
        public virtual DateTime FailedPasswordAnswerAttemptWindowStart { get; set; }
        public virtual IList<roles> Roles { get; set; }

        public Users()
            this.CreationDate = Utils.MinDate();
            this.LastPasswordChangedDate = Utils.MinDate();
            this.LastActivityDate = Utils.MinDate();
            this.LastLockedOutDate = Utils.MinDate();
            this.FailedPasswordAnswerAttemptWindowStart = Utils.MinDate();
            this.FailedPasswordAttemptWindowStart = Utils.MinDate();
            this.LastLoginDate = Utils.MinDate();
        public virtual void AddRole(Roles role)

        public virtual void RemoveRole(Roles role)

Similar entity classes exist for Role (see the project file for details).


Mappings folder contains the Fluent Nhibernate equivalent of the XML mappings. In UsersMap “Has ManyToMany” identifies the relationship to roles via the “UsersInRoles” table. Conversely in RolesMap HasManyToMany has an inverse relationship to “UsersInRoles”.

public class UsersMap: ClassMap<users>
        public UsersMap()
            Id(x => x.Id);
            Map(x => x.Username);
            Map(x => x.ApplicationName);
            Map(x => x.Email);
            Map(x => x.Comment);
            Map(x => x.Password);
            Map(x => x.PasswordQuestion);
            Map(x => x.PasswordAnswer);
            Map(x => x.IsApproved);
            Map(x => x.LastActivityDate);
            Map(x => x.LastLoginDate);
            Map(x => x.LastPasswordChangedDate);
            Map(x => x.CreationDate);
            Map(x => x.IsOnLine);
            Map(x => x.IsLockedOut);
            Map(x => x.LastLockedOutDate);
            Map(x => x.FailedPasswordAttemptCount);
            Map(x => x.FailedPasswordAnswerAttemptCount);
            Map(x => x.FailedPasswordAttemptWindowStart);
            Map(x => x.FailedPasswordAnswerAttemptWindowStart);

            HasManyToMany(x => x.Roles )

Similar mapping classes exist for Role (see the solution file for details).

Membership Provider

The actual implementation of the membership provider is in the class FNHMembershipProvider. This class inherits from the Security.MembershipProvider class. It provides overrides for all the methods available in the base class. In this class, I have replaced all the data access code with Fluent Data access code via the NHibernate session factory. There are several other methods that are to be implemented in the class, here we will look at two of them. In the GetUserNameByEmail, we see an example of how we query by criteria using Nhibernate, returning strongly typed Entity Users:

public override string GetUserNameByEmail(string email)
            Entities.Users usr = null;
            using (ISession session = SessionFactory.OpenSession())
                using (ITransaction transaction = session.BeginTransaction())

                        usr = session.CreateCriteria(typeof(Entities.Users))
                              .Add(NHibernate.Criterion.Restrictions.Eq("Email", email))
                              .UniqueResult < Entities.Users>();
                    catch (Exception e)
                            WriteToEventLog(e, "GetUserNameByEmail");
                        throw new ProviderException(exceptionMessage);
            if (usr == null)
                return string.Empty;
                return usr.Username; ;

CreateUser procedure creates a new membership user, it uses Session.Save to save the user information to the database:

public override MembershipUser CreateUser(string username,
                 string password,
                 string email,
                 string passwordQuestion,
                 string passwordAnswer,
                 bool isApproved,
                 object providerUserKey,
                 out MembershipCreateStatus status)
            ValidatePasswordEventArgs args =
        new ValidatePasswordEventArgs(username, password,true);

            if (args.Cancel)
                status = MembershipCreateStatus.InvalidPassword;
                return null;

            if (RequiresUniqueEmail && GetUserNameByEmail(email) != "")
                status = MembershipCreateStatus.DuplicateEmail;
                return null;

            MembershipUser u = GetUser(username, false);

            if (u == null)
                DateTime createDate = DateTime.Now;

                //provider user key in our case is auto int

                using (ISession session = SessionFactory.OpenSession())
                    using (ITransaction transaction = session.BeginTransaction())
                        Entities.Users user = new Entities.Users();
                        user.Username = username;
                        user.Password = EncodePassword(password);
                        user.Email = email;
                        user.PasswordQuestion = passwordQuestion;
                        user.PasswordAnswer = EncodePassword(passwordAnswer);
                        user.IsApproved = isApproved;
                        user.Comment = "";
                        user.CreationDate = createDate;
                        user.LastPasswordChangedDate = createDate;
                        user.LastActivityDate = createDate;
                        user.ApplicationName = _applicationName;
                        user.IsLockedOut = false;
                        user.LastLockedOutDate = createDate;
                        user.FailedPasswordAttemptCount = 0;
                        user.FailedPasswordAttemptWindowStart = createDate;
                        user.FailedPasswordAnswerAttemptCount = 0;
                        user.FailedPasswordAnswerAttemptWindowStart = createDate;

                            int retId = (int)session.Save(user);

                            if ((retId <1))
                                status = MembershipCreateStatus.UserRejected;
                                status = MembershipCreateStatus.Success;
                        catch(Exception e)
                            status = MembershipCreateStatus.ProviderError;
                                WriteToEventLog(e, "CreateUser");

                //retrieve and return user by user name
                return GetUser(username, false);
                status = MembershipCreateStatus.DuplicateUserName;
            return null;


The implementation of Role provider FNHRoleProvider involves overriding the Security.RoleProvider class. It has methods for creating/deleting roles, for adding/removing users to/from roles and querying roles. The method shown below creates a role based on a given role name.

public override void CreateRole(string rolename)
            if (rolename.Contains(","))
                throw new ArgumentException("Role names cannot contain commas.");

            if (RoleExists(rolename))
                throw new ProviderException("Role name already exists.");

            using (ISession session = SessionFactory.OpenSession())
                using (ITransaction transaction = session.BeginTransaction())
                        Entities.Roles  role = new Entities.Roles();
                        role.ApplicationName = this.ApplicationName;
                        role.RoleName = rolename;
                    catch (OdbcException e)
                        if (WriteExceptionsToEventLog)
                            WriteToEventLog(e, "CreateRole");
                            throw e;

Each of the providers has an initialize method which reads the configuration values from the web.config file that initializes each provider with the default settings.


This static class is used to configure the connection to the database and create a session factory. I am using a connection to a SQL Server 2005, but you can easily change the database to any other supported database (MySql, Oracle, Jet, MsSqlCe, PostGre, SqlLite) without any other code changes. That’s the beauty of Nhibernate. You can read more about the database configurations in Fluent Nhibernate here.
public static ISessionFactory CreateSessionFactory(string connstr)
            return Fluently.Configure()

                .Mappings(m =>


Sample Application

This is a sample application (FNHCustomProviders.SampleApp) which demonstrates the use of the Fluent Nhibernate Membership provider. The application contains simple aspx pages which are used to:

  • Create User
  • Manage password/forgot password
  • Manage users and roles

The Manage User and Roles page allows you to add/delete a role and assign/remove users to/from roles.


Putting It All Together

  1. Database: Creates the database and tables using the script
  2. FNH Membership Provider: Compiles as INCT.FNHProviders.dll. You should have the following supporting assemblies present in your bin folder for a successful build.
    • Antlr3.Runtime.dll
    • Castle.Core.dll
    • Castle.Core.xml
    • Castle.DynamicProxy2.dll
    • Castle.DynamicProxy2.xml
    • FluentNHibernate.dll
    • Iesi.Collections.dll
    • Iesi.Collections.xml
    • INCT.FNHProviders.dll
    • log4net.dll
    • log4net.xml
    • nhibernate-mapping.xsd
    • NHibernate.ByteCode.Castle.dll
    • NHibernate.ByteCode.Castle.xml
    • NHibernate.dll
    • NHibernate.xml
  3. FNHCustomProviders.SampleApp: Needs a reference to FluentNHibernate and FNHCustomProviders. You should have the following sections in the webconfig set up for the app to run. This should go inside system.web section.
  4. If you want to use the email password feature, then mail settings section needs to be there:


  5. Lastly, you need to change the connection string to point to your own database.


I have added a profile provider to the existing project. The profile I have implemented is simple but suffices for most needs. It is added to the project as a separate zip file and includes the membership, role and profile provider. This also contains the web-config section to be modified and the additional table for profile. Look for other settings.txt in the zip. It contains the web-config changes and the table scripts.

Updates Profile provider

I realized there were some questions about usage of profile provider. I added a zip file with usage sample. Two things need to be added a)In your project add UserProfileBase class (usage (b)In web.config use the inherits attribute of Profile provider to point to the location of UserProfileBase For usage something like this will work :

//get a profile 
 UserProfileBase profile = UserProfileBase.GetUserProfile(Page.User.Identity.Name);
                string i = profile.UserName;
//creates profile ;
                profile.City = "stl";
                profile.BirthDate = System.DateTime.Now.AddYears(-30);
                profile.FirstName = "Suhel";
                profile.Gender = "M";
                profile.Language = "English";
                profile.LastName = "s";
                profile.Occupation = "Director";
                profile.State = "mo";
                profile.Street = "123 main";
                profile.Subscription = "yes";
                profile.Website = "";
                profile.Zip = "1234";
                profile.Country = "US";



  • 29th January, 2010: Initial post
  • 7th June, 2010: Article updated


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Suhel Shah
United States United States
Lead Enterprise Application development and architecture using with back end databases like Ms-SQL, Oracle.

You can contact me at

You may also be interested in...


Comments and Discussions

QuestionHow to create use this tutorial for MySql or Postgresql? Pin
manukharde2-Jul-16 19:45
membermanukharde2-Jul-16 19:45 
GeneralMy vote of 5 Pin
Prasad Khandekar24-Oct-14 5:42
professionalPrasad Khandekar24-Oct-14 5:42 
Questionupdate to work with dotnet version 4.0 Pin
6-Oct-14 6:02
member6-Oct-14 6:02 
QuestionMaybe a bug Pin
JZO_5-Mar-14 4:25
memberJZO_5-Mar-14 4:25 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey13-Aug-12 0:46
memberManoj Kumar Choubey13-Aug-12 0:46 
QuestionNot at all bad Pin
MarkAusten13-Apr-12 22:09
memberMarkAusten13-Apr-12 22:09 
GeneralMy vote of 5 Pin
Saleem CB30-Mar-12 20:54
memberSaleem CB30-Mar-12 20:54 
QuestionProfile Provider Pin
Saleem CB30-Mar-12 20:50
memberSaleem CB30-Mar-12 20:50 
AnswerRe: Profile Provider Pin
MarkAusten13-Apr-12 21:43
memberMarkAusten13-Apr-12 21:43 
GeneralRe: Profile Provider Pin
Saleem CB17-Apr-12 6:51
memberSaleem CB17-Apr-12 6:51 
GeneralRe: Profile Provider Pin
Suhel Shah12-Aug-12 10:16
memberSuhel Shah12-Aug-12 10:16 
QuestionSuggestion Pin
botskie15-Feb-12 21:05
memberbotskie15-Feb-12 21:05 
QuestionHow to get records order by UserCount Pin
PraveenSabbisetti7-Jan-12 1:25
memberPraveenSabbisetti7-Jan-12 1:25 
GeneralNot too bad to port to Postgres either Pin
eloquence23-Nov-10 14:56
membereloquence23-Nov-10 14:56 
GeneralRe: Not too bad to port to Postgres either Pin
Suhel Shah6-Dec-10 8:43
memberSuhel Shah6-Dec-10 8:43 
GeneralMy vote of 5 Pin
eloquence23-Nov-10 14:51
membereloquence23-Nov-10 14:51 
GeneralRe: My vote of 5 Pin
Suhel Shah6-Dec-10 8:34
memberSuhel Shah6-Dec-10 8:34 
GeneralModifying existing profile Pin
ghallas27-Jul-10 2:31
memberghallas27-Jul-10 2:31 
GeneralRe: Modifying existing profile Pin
ghallas29-Jul-10 23:13
memberghallas29-Jul-10 23:13 
GeneralRe: Modifying existing profile Pin
Suhel Shah30-Jul-10 5:05
memberSuhel Shah30-Jul-10 5:05 
GeneralRe: Modifying existing profile Pin
ghallas1-Aug-10 20:41
memberghallas1-Aug-10 20:41 
GeneralAny plans on upgrading the code to be used with the 1.0.0.* release of the FluentNHibernate.dll Pin
bert in bert land6-Jul-10 0:26
memberbert in bert land6-Jul-10 0:26 
GeneralRe: Any plans on upgrading the code to be used with the 1.0.0.* release of the FluentNHibernate.dll Pin
bert in bert land6-Jul-10 1:54
memberbert in bert land6-Jul-10 1:54 
GeneralRe: Any plans on upgrading the code to be used with the 1.0.0.* release of the FluentNHibernate.dll Pin
Suhel Shah30-Jul-10 5:06
memberSuhel Shah30-Jul-10 5:06 
GeneralProfile Provider Pin
Gene Myers26-May-10 5:16
memberGene Myers26-May-10 5:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01-2016 | 2.8.180920.1 | Last Updated 13 Aug 2012
Article Copyright 2010 by Suhel Shah
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid