Discuss this topic on our forums
DotNetNuke uses the "Providers" pattern extensively in order for developers to change functionality without having to modify the Core code base. Using well known interfaces and/or abstract classes developers are able to "plug-in" new behavior for their implementation and ultimately can be used by custom module(s). For the core code executing against these classes, it is none the wiser as to the "how" or "where" the custom implementation is running or handling requests, if at all. DNN Membership and Role providers are examples of this pattern.
This document was developed using DotNetNuke 4.3.4, but should work for other versions of DotNetNuke 4.3.*
This document intent is to provide DNN developers a "starting point" source of information to replacing the out of the box ASPNetMembersShipProvder with a custom provider. Included are also some important considerations that will need to be made before you begin development and how you can get started programming your implementation.
If you are considering replacing the Membership functionality you should ask yourself these questions:
- Why am I replacing the membership (authentication) in the first place? The answer should be that I already have an existing data store with a user base and I want to validate user from my DNN site against.
- Can I achieve what I need by adding on to the existing functionality provided or am I replacing the user's data store and the validation process entirely? In some cases, it may make more sense to sync the users and passwords into the default ASPNET tables. This could be desirable if the long term strategy is to phase out the other system entirely.
- Does the other system that I plan on replacing provide enough functionality to satisfy the abstract MembershipProvider that DNN uses? Important! You must look through the list of methods/properties that this abstract class contains and be sure that you can provide answers to those questions as needed in order for your implementation to work seamlessly.
- Can I retrieve a decrypted password from the new data store? It is important to understand how you will handle password resets, forgot password and random password generation before you start. Otherwise you will not be able to provide this functionality in your custom provider.
Understanding all the Pieces
Before you begin, it is very important to understand all the pieces within DNN. What are the membership and role providers? The first step is to locate the abstract classes (or concrete classes) that your implementation will be extending and examine all the signatures and their behavior. During this process you should be asking the question "how will my version answer these questions?". Below is an overview of the Membership and Roles implementation that should provide a good starting point for your project.
The membership provider provides the membership functions to allow a user access to your DNN site. i.e. Validating username/password. The default install for DNN uses ASPNetMembersShip provider. This provider class does not extend the Microsoft SqlMemberShipProvider class as with the previous versions of DNN. This is a very important difference. The ASPNetMembership class extends a DNN class DotNetNuke.Security.Membership.MembershipProvider which has a lot of the same signatures as the built in System.Web.Security.SqlMembershipProvider class. The ASPNetMembersShip class essentially forwards every request to the built in implementation from Microsoft to perform reads/writes to the ASPNET_* tables. The fundamental shift in thinking here is that DNN has implemented their own abstract class instead of programming against the System.Web.Security.SqlMembershipProvider (or MembershipProvider) class provided in the .NET Framework.
In some cases you may only need to authenticate your users via the primary data store. If your situation requires roles to be propagated to DNN you will need to make decisions about how roles correlate from the primary data store to the DNN role table. The RoleController and RoleInfo classes provide behavior for you to manage roles within DNN. In the simplest scenario, your DNN site will include a custom scheduled job to keep these in sync.
Interestingly enough, DNN uses the DNNRoleProvider class to provide role management locally and does not manage ASPNET Roles (aspnet_roles). Previous versions of DNN forwarded requests to the System.Web.Security.Roles.* methods in the same way that membership currently does.
What you need
- You will need to download the source code for DotNetNuke 4.*
- You will need to download and install the DNN Starter Kit on your development machine.
- A blank SQL Server database named appropriately. This database will contain the DNN tables for your new site.
Configuring your DNN Environment
Download and install the DNN Starter Kit and install onto your computer. Start VS 2005 and select File à New Web Site. In the list you should see DotNetNuke Web Application Framework under My Templates. Select this option and provide a location/name for your web site. At this point the Starter Kit will create a default site for you and add references to your project (web site) to all required components. You should see a Quick Installation page that has some instructions about pointing to a database and how to configure. You will need a blank database specified in the web.config file the first time you run the site in order to install DNN and all related tables. Once you have created/configured the database go to the property pages for the site and look through the references for DotNetNuke.Providers.AspNetProvider. This reference is the reference that you will need remove and re-add as a project reference.
Now you need to locate the source code for DotNetNuke.Providers.AspNetProvider. This is located in Source\Library\Providers\MembershipProviders\AspNetMembershipProvider. It is a good idea to use this project code base as a starting point for your new MemberShipProvider. Make a folder (not under the web site) with the appropriate name i.e. EngageMembershipProvider and copy all the files into this folder. Next go to your web site references and remove the DotNetNuke.Providers.AspNetProvider reference. This step disconnects you from the default install for membership. Now add the project to your solution. Lastly, add a reference from your web site to your new MembershipProvider project. Note: This is a good time to change the name of the project, AspNetMembershipProvider.vb and so on. Once you have cleaned up the names of the project, class files and the output file name (????.dll) add the reference to your project.
Now, in order for DNN to load your Membership Provider you will need to update the web.config file. Scroll down to find the <members> section of the file. You will need to update the path and assembly name to your new name.
<add providerpath="~" type="DotNetNuke.Engage.Provider.EngageMembershipProvider, DotNetNuke.Engage.Provider" name="EngageMembershipProvider" />
Within your website your may notice there is a setting for DNN that tells the install whether or not to install the Membership tables.
<add value="True" key="InstallMemberRole" />
The logic here is that you are replacing the default membership provider with a custom implementation that is pointing to totally different database/tables so why should I need the membership tables installed?
Do not change this setting if you are creating a brand new site/install. An existing bug with DNN attempts to read values from the aspnet_SchemaVersions table using the aspnet_CheckSchemaVersion stored procedure and will cause your install to fail. Until this issue is resolved with DNN you will have to either a) leave the membership tables, procedures and views in your database which is messy or b) selectively remove all database objects (except the two mentioned above) from your database afterwards.
At this point you should be able to run your application, if this is the first time the DNN install will begin and afterwards you can access your default DNN web site. You are setup with your new provider in Debug mode and can begin reviewing the methods on the AspNetMembershipProvider (or whatever you renamed it to) and begin thinking about how to replace the behavior to work against whatever data source you would like.
As you go through the steps of creating your own provider you may notice some things about the DNN implementation that contradicts the idea of a "Provider". With DNN's current implementation you cannot escape the local DNN tables. This is also true for the roles (and probably profile as well). In the end, this means that you will be creating/validating/managing users in two databases. You will need to make decisions about which attributes you will need to keep in sync (if any) i.e. email, name.
This version of Membership is greatly improved from previous versions and paves the way for developers to provide their own implementations running against existing data stores. This is a powerful sell point for DNN and allows enterprise level modules to be developed without expensive data migration and provides a consistent login for users.
About Henry Kenuam
Henry Kenuam is a co-founder of Engage Software and Chief Technology Officer. His responsibilities include overseeing the technical direction of the company. Henry ensures that the technologies used in software development efforts are proven and that the system designs are of the highest quality. He has over 13 years of Information Technology experience in Software Development and Design. Previously, Henry has managed multi-million dollar software development projects for Maritz. On the largest, a custom CRM (Customer Relationship Management) system for Toyota/Lexus (1-800-GOTOYOTA), Henry served as System Architect and Project Manager.
Discuss this topic on our forums