Shining Star Services LLC

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">
                                    &nbsp;
                                </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
© Copyright 1997-2017 Shining Star Services LLC, Nannette Thacker. All Rights Reserved.