Creating a Custom Membership Provider and Membership User utilizing
a Data Set Table Adapter - Step 10
by Nannette Thacker
Our Master Page
Below is our Master Page in front code:
<%@ Master Language="VB" CodeFile="SSS.master.vb" Inherits="SSSMaster" %>
<%@ Register TagPrefix="uc" TagName="MenuSSS" Src="~/Controls/PageElements/MenuSSS.ascx"%>
<%@ Register TagPrefix="uc" TagName="Copyright" Src="~/Controls/PageElements/Copyright.ascx"%>
<%@ Register TagPrefix="uc" TagName="AdminLinks" Src="~/Controls/PageElements/AdminLinks.ascx"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Nannette Thacker's Custom Membership Provider Application</title>
</head>
<body>
<form id="form1" runat="server">
<div id="wrapper">
<div id="MastHead">
<table cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="LogoBlack">
<center>
<table cellpadding="0" cellspacing="0" class="ContentWidth">
<tr>
<td class="LogoText">
<table border="0" cellspacing="0" class="bottomborder">
<tr>
<td>
<a href="<%= ResolveClientUrl("~/")%>" class="Logo"></a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</center>
</td>
</tr>
</table>
</div>
<table cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="ContentBack">
<center>
<table cellpadding="0" cellspacing="0" class="ContentWidth">
<tr>
<td width="151" valign="top" class="PadLeft5">
<div class="SidebarTop">
</div>
<div class="SidebarHead">
</div>
<div class="SidebarMenu">
<uc:MenuSSS ID="MenuSSS2" runat="server" />
</div>
<div class="SidebarTop">
</div>
</td>
<td class="DividerTab">
</td>
<td width="496" valign="top">
<div class="ContentRight">
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</td>
</tr>
</table>
</center>
</td>
</tr>
<tr>
<td class="ContentDividerTop">
</td>
</tr>
<tr>
<td class="ContentDividerMiddle">
</td>
</tr>
<tr>
<td class="ContentBottom">
<center>
<table cellpadding="0" cellspacing="0" class="ContentWidth, LogoText">
<tr>
<td class="FooterPanels">
<div class="FooterPanelsText">
Web Application Development</div>
ASP.NET, VB, C#, SQL Server, Cascading Style Sheets
</td>
<td class="FooterPanels">
<div class="FooterPanelsText">
Web Design</div>
Web Sites, Logos, Adobe PhotoShop, Adobe Illustrator
</td>
<td class="FooterPanels">
<div class="FooterPanelsText">
Conversions</div>
ASP Classic to ASP.NET Conversions<br />
<br />
</td>
</tr>
</table>
</center>
</td>
</tr>
</table>
<table cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="FooterBlack">
<center>
<table cellpadding="0" cellspacing="0" class="ContentWidth">
<tr>
<td width="100%">
<div class="footerlinks">
<uc:Copyright ID="Copyright1" runat="server" />
<uc:AdminLinks ID="AdminLinks1" runat="server" Visible="false" />
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
<asp:Label ID="Label2" runat="server" Text=""></asp:Label>
</div>
</td>
</tr>
</table>
</center>
</td>
</tr>
<tr>
<td class="ContentDividerTop">
</td>
</tr>
</table>
</div>
</form>
</body>
</html>
Below is our code behind. Notice, we have set our UserName property as Bindable so that it can be used in controls. We check if the user is logged in, and if not, we check the user's cookies to see if they had selected the Remember Me checkbox on the Log in page.
Imports System.Web
Imports System.Web.Security
Imports SSSCookie
Imports ShiningStar.SSSRole
Partial Class SSSMaster
Inherits BaseMaster
Private _userid As Integer = 0
Private _isAdmin As Boolean = False
Private _isLoggedIn As Boolean = False
Private _userName As String = ""
Public _userPassword As String = ""
Public _userEmail As String = ""
#Region "URLs"
' http://msdn2.microsoft.com/en-us/library/ms178472.aspx
' page lifecycle overview...
' http://www.odetocode.com/Articles/450.aspx
#End Region
Protected Sub pageInit(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Init
' nkt set to handle Init.... this triggers before the Page_Loads....
Call UserLogin()
End Sub
Protected Sub UserLogin()
' the Master Page PreInit Fires before the PageLoad each page
Dim myUser As ShiningStar.SSSMembershipUser = Nothing
Dim UserCookie As New SSSCookie()
IsLoggedIn() = Page.User.Identity.IsAuthenticated
If IsLoggedIn Then
myUser = Membership.GetUser(Page.User.Identity.Name, IsLoggedIn) ' uses adapter
UserName = myUser.UserName
Else
' check cookies if not logged on...
UserID = UserCookie.GetUserID
If CLng(UserID) <> 0 Then ' if it is saved, then get the user info...
Dim myMemberW As New ShiningStar.SSSMembershipProviderWrapper
myUser = myMemberW.GetUser(UserID)
UserName = myUser.UserName
End If
End If
Dim scriptname As String
scriptname = UCase(Request.ServerVariables("SCRIPT_NAME"))
If Not String.IsNullOrEmpty(UserName) Then ' if the user exists in the database
UserID = myUser.userID
UserPassword = myUser.Password
UserEmail = myUser.Email
If Not IsLoggedIn Then ' if user exists, and haven't logged in yet, validate them
If Not String.IsNullOrEmpty(UserID) And CStr(UserID) <> "0" Then ' if id stored in cookie...
If InStr(scriptname, "LOGIN") = 0 Then ' if not on log in page, do this
Dim isUserValid As Boolean = UserCookie.CompareCheckSum(UserID.ToString, UserName, UserPassword)
If Not isUserValid And InStr(scriptname, "LOGIN") = 0 Then ' if not on log in page, go there...
System.Web.HttpContext.Current.Response.Redirect("~/login/login.aspx", False)
ElseIf isUserValid And Not IsLoggedIn Then
' if user is valid from cookie checksum, but not yet logged in, then validate them...
Dim myProvider As New ShiningStar.SSSMembershipProvider
Dim isValidated As Boolean = myProvider.ValidateUser(UserName, UserPassword)
If isValidated Then
FormsAuthentication.SetAuthCookie(UserName, True)
'IsLoggedIn = Page.User.Identity.IsAuthenticated
IsLoggedIn = isValidated
End If
End If
End If
End If
End If
End If
If IsLoggedIn Then
If UCase(Roles.IsUserInRole(UserName, "ADMIN")) Then
IsAdmin() = True
End If
End If
If UCase(Roles.IsUserInRole("BLOCK")) And InStr(UCase(scriptname), "SORRY") = 0 Then
System.Web.HttpContext.Current.Response.Redirect("~/Login/Sorry.aspx", False)
End If
If IsAdmin Then ' if an admin...
Me.AdminLinks1.Visible = True
Else
Me.AdminLinks1.Visible = False
End If
If myUser Is Nothing Then
UserName = "Guest"
Else
Call SetLabels(UserName)
End If
End Sub
Protected Sub SetLabels(ByVal IHUserName As String)
If Not String.IsNullOrEmpty(IHUserName) Then
Label1.Text = "User ID: " & UserID.ToString & _
" Name: " & IHUserName.ToString
End If
End Sub
#Region "Set as Properties to be used in controls. MustOverride in BaseMaster.vb"
Public Overrides Property UserID() As Integer
Get
Return _userid
End Get
Set(ByVal value As Integer)
_userid = value
End Set
End Property
' set bindable so can pass as property in a control
<ComponentModel.Bindable(True)> Public Overrides Property UserName() As String
' define to be used in control
Get
Return _userName
End Get
Set(ByVal value As String)
_userName = value
End Set
End Property
Public Overrides Property UserPassword() As String
Get
Return _userPassword
End Get
Set(ByVal value As String)
_userPassword = value
End Set
End Property
Public Overrides Property UserEmail() As String
Get
Return _userEmail
End Get
Set(ByVal value As String)
_userEmail = value
End Set
End Property
Public Overrides Property IsLoggedIn() As Boolean
Get
Return _isLoggedIn
End Get
Set(ByVal value As Boolean)
_isLoggedIn = value
End Set
End Property
Public Overrides Property IsAdmin() As Boolean
Get
Return _isAdmin
End Get
Set(ByVal value As Boolean)
_isAdmin = value
End Set
End Property
#End Region
End Class
Below is our BaseMaster.vb class. It allows us to retrieve property values from the master page to be used within a control.
Be sure to read the comments in the Explanation regions below for how and why to use this:
Imports Microsoft.VisualBasic
#Region "Explanation of MasterType in Content Pages"
' MASTERTYPE for CONTENT PAGES:
' set the MasterType under the @Page directive of the content
' page .aspx file
' <%@ MasterType VirtualPath="~/SSS.master" %>
' see admin/devtest.aspx
'make sure the variable or function is declared as public
' within the MasterPage codebehind class.
' use the word: Master. to retrieve the master variables
' Dim myUserLevel As String = Master.UserLevel ' if not admin,
' don't allow access...
' can also call function
' Call Master.UserLogin() ' (this is not public, but this is
' an example if it were)....
#End Region
#Region "Explanation of BaseMaster Usage in Controls"
' this can be used in or out of controls (in content pages),
' but it must be used in controls for VB.
' to call MasterPage variables within a control, you need to
' define those variables here
' the content pages can easily retrieve master page variables
' by doing this:
' FOR CONTROLS...
' Controls do not support the MasterType, so you cannot call the
' master variables with "Master."
' this does not work:
' Dim d As Decimal = CType(Me.Page.Master, SSS_Master).UserLevel
' various variations produce:
' Compiler Error Message: BC30451: Name 'SSS_Master' is not declared.
' Compiler Error Message: BC30456: 'UserLevel' is not a member of
' 'System.Web.UI.MasterPage'.
' Type 'SSS_Master' is not defined.
'1. Defined a new class called BaseMaster in App_Code
' Public MustInherit Class BaseMaster
' Inherits MasterPage
'2. Defined a UserLevel property in it with MustOverride access
' modifier
'3. Made master page to inherit from BaseMaster class
'4. Overrided UserLevel property
'From this point you can use
' Dim d As Decimal = CType(Me.Page.Master, BaseMaster).UserLevel
' it seems that: VB is not able to cast to some page's type because
' for some reason even the compiler does not see it
' Other way around this would be to define some Interface and
' make master page implement it.
' Then user control would be able to cast as well...
' This is evidentally not a problem in C#.
#End Region
Public MustInherit Class BaseMaster
Inherits System.Web.UI.MasterPage
Public MustOverride Property UserID() As Integer
Public MustOverride Property UserName() As String
Public MustOverride Property UserPassword() As String
Public MustOverride Property UserEmail() As String
Public MustOverride Property IsAdmin() As Boolean
Public MustOverride Property IsLoggedIn() As Boolean
End Class
We are now ready to begin
Step 11.
Steps for Creating a Custom Membership Provider and Membership
User utilizing a DataSet Table Adapter:
Introduction: Creating a Custom Membership Provider and Membership User utilizing
a DataSet Table Adapter.
Step 1: Creating the Project and Folders.
Step 2: Table Data Structure and Web.config for this Tutorial.
Step 3: Creating The DataSet.
Step 4: Creating the Table Adapter Methods for GetUserByLogin, GetUserByUserName, and InsertUser.
Step 5: Creating our Custom MembershipProvider Class.
Step 6: Adding Properties to Our Custom MembershipProvider Class.
Step 7: Creating Our Custom MembershipUser Class.
Step 8: Customizing our MembershipProvider Class.
Step 9: Our Custom RoleProvider Class.
Step 10: Our Master page.
Step 11: Our Cookie Handler class.
Step 12: Our Log In page.
Step 13: Our Register page.
Step 14: Our Log Out page.
Step 15: Our Change Password page.
Step 16: Our Administration page.
Step 17: Loading a Menu Programmatically based on Roles.
Step 18: Our Default page.
Download the ZIP files:
VB: ShiningStarCustomMemberProviderTutorial.zip