ASP.NET 2.0: Login Controls...
Previously on DotNetJohn I wrote about creating a Login control that allowed the user to login to a site. By establishing a membership provider through the ASP.NET configuration tool, the 2.0 framework supports membership handling through a SQL Server or Access database by default, but custom providers can be created to include Oracle or other data stores if needed.
Previously on DotNetJohn ( http://www.dotnetjohn.com/articles.aspx?articleid=126) I wrote about creating a Login control that allowed the user to login to a site. When the credentials were entered and the user hit the submit button, an event was thrown, allowing the application to query a data source for the credentials information. The success or failure of the login was available through separate events, and could be handled by the user interface to display a message to the user. In the .NET Framework 2.0 beta, a series of controls handle login capabilities, taking the login process to a higher level.
By establishing a membership provider through the ASP.NET configuration tool, the 2.0 framework supports membership handling through a SQL Server or Access database by default. Custom providers can be created to include Oracle or other data stores if needed. Providers store information about users, roles, application personalization, site counter information, and more, managed automatically through the server controls provided in the framework. Very little coding is needed, as shown in this article. This article will focus on Login controls.
With the newer version of the framework, naturally existing controls evolve and new controls appear, such as the Login control. This control provides forms-based sites with the capabilities to login, as well as the persistence of the authentication credentials through cookies. It eliminates the need for a custom control, user control, or custom code to represent the login screen, while offering flexibility through its properties. The text or styles that appear within the control can be fully customizable through a set of properties available in the control. The properties are pretty self-explanatory, and the naming scheme usually is consistent.
This article will show a basic example of the Login controls using a Membership provider, and will illustrate the minimal amount of code actually written to operate the site. Later on, more articles will detail each control individually, as this example will not delve into the properties, methods, and events available.
|
<asp:Login ID="lgnLogin" Runat="server" CreateUserUrl="~/createuser.aspx" CreateUserText="Create a New Account" UserNameLabelText="User ID:" BorderStyle="Solid" BorderWidth="1px" BorderColor="#B5C7DE" BorderPadding="4" BackColor="#EFF3FB" ForeColor="#333333" Font-Names="Verdana" Font-Size="0.8em"> <InstructionTextStyle Font-Italic="True" Font-Size="0.8em" ForeColor="Black"></InstructionTextStyle> <CheckBoxStyle Font-Size="0.8em"></CheckBoxStyle> <TextBoxStyle Font-Size="0.8em"></TextBoxStyle> <LabelStyle Font-Size="0.8em"></LabelStyle> <TitleTextStyle Font-Size="0.9em" Font-Bold="True" BackColor="#507CD1" ForeColor="White"></TitleTextStyle> <HyperLinkStyle Font-Size="0.8em"></HyperLinkStyle> <SubmitButtonStyle Font-Names="Verdana" Font-Size="0.8em" BorderStyle="Solid" BorderWidth="1px" BorderColor="#507CD1" BackColor="White" ForeColor="#284E98"></SubmitButtonStyle> <FailureTextStyle Font-Size="0.8em" ForeColor="#FF0000"></FailureTextStyle> </asp:Login> |
When the user logs into the application, then name of the authenticated user can be made available in the application. The LoginName control handles this by automatically rendering the name of the user. For custom text, specify a format string, and place the user name in the text using the {0} placeholder.
| <asp:LoginName ID="lgnName" Runat="server" FormatString="Welcome {0}" /> |
When the user logs in, normally in an authenticated site a link allows the user to logout. Upon clicking the logout button, the link changes to a login text, allowing the user to login. The previous approach was to detect the user’s logged in status; however, a better control is available. The LoginStatus control automatically detects the user’s login status, and renders the appropriate link. When the user logs out, certain actions can occur; the application can refresh at the current page, can redirect to a custom URL, or redirect to the login page (specified in the configuration file). This is managed by the LogoutAction property, which stored an enumerated value. If the custom URL redirection option is chosen, the application redirects to the URL specified in the LogoutPage property.
If the user is logged off, this link will display the Login text, which will redirect to the specified login page. If the "remember me" checkbox option is checked, the login credentials are stored in cookies and the link status renders correctly with the "Logout" text.
| <asp:LoginStatus ID="lstLogin" Runat="server" /> |
You see a lot of web sites out there that require the user to login to view the content. User accounts are usually free; however, registration is required. The LoginView makes this feature easy. By using two templates, the appropriate content is shown based on the login status. These two templates are the <AnonymousTemplate> and <LoggedInTemplate> elements, which are appropriately named. One of the new features of templated controls is the capabilities to switch between views at design time, similar to the data grid control. In a data grid control that has template columns defined, the user can right-click the control and select the template to edit.
The LoginView control is not only useful for forcing users to login; it is also useful for rendering member-only options available in the site, such as controls that modify preferences, colors, or other personalizable settings.
|
<asp:LoginView ID="lvwLogin" Runat="server"> <LoggedInTemplate> <asp:LoginName ID="lgnName" Runat="server" FormatString="Welcome {0}" /><br /> <asp:LoginStatus ID="lstLogin" Runat="server" /><br /> <asp:HyperLink ID="lnkChangePassword" Runat="server" NavigateUrl="~/changepw.aspx">Change Password</asp:HyperLink> <br /> <br /> <asp:contentplaceholder id="plcUserSettings" runat="server"></asp:contentplaceholder> </LoggedInTemplate> <AnonymousTemplate> <asp:Login ID="lgnLogin" Runat="server" CreateUserUrl="~/createuser.aspx" CreateUserText="Create a New Account" UserNameLabelText="User ID:" BorderStyle="Solid" BorderWidth="1px" BorderColor="#B5C7DE" BorderPadding="4" BackColor="#EFF3FB" ForeColor="#333333" Font-Names="Verdana" Font-Size="0.8em"> <InstructionTextStyle Font-Italic="True" Font-Size="0.8em" ForeColor="Black"></InstructionTextStyle> <CheckBoxStyle Font-Size="0.8em"></CheckBoxStyle> <TextBoxStyle Font-Size="0.8em"></TextBoxStyle> <LabelStyle Font-Size="0.8em"></LabelStyle> <TitleTextStyle Font-Size="0.9em" Font-Bold="True" BackColor="#507CD1" ForeColor="White"></TitleTextStyle> <HyperLinkStyle Font-Size="0.8em"></HyperLinkStyle> <SubmitButtonStyle Font-Names="Verdana" Font-Size="0.8em" BorderStyle="Solid" BorderWidth="1px" BorderColor="#507CD1" BackColor="White" ForeColor="#284E98"></SubmitButtonStyle> <FailureTextStyle Font-Size="0.8em" ForeColor="#FF0000"></FailureTextStyle> </asp:Login> </AnonymousTemplate> </asp:LoginView> |
The CreateUserWizard control is inherited from the new Wizard control. The Wizard control scrolls through screen-by-screen, in an orderly fashion. The CreateUserWizard control in particular contains a set of pre-defined properties useful for registering new users in the site. Additional templates exist for displaying custom information.
|
<asp:CreateUserWizard ID="cuzNewUser" Runat="server" BackColor="#EFF3FB" Font-Names="Verdana" Font-Size="0.8em" BorderStyle="Solid" BorderColor="#B5C7DE" BorderWidth="1px"> <WizardSteps> <asp:CreateUserWizardStep ID="CreateUserWizardStep1" Runat="server" Title="Sign Up for Your New Account"> </asp:CreateUserWizardStep> <asp:CompleteWizardStep ID="CompleteWizardStep1" Runat="server" Title="Complete"> </asp:CompleteWizardStep> </WizardSteps> <StepStyle BorderColor="#B5C7DE" Font-Names="Verdana" Font-Size="0.8em" BackColor="#EFF3FB" BorderStyle="Solid" BorderWidth="1px"></StepStyle> <TitleTextStyle Font-Bold="True" BackColor="#507CD1" ForeColor="White"></TitleTextStyle> </asp:CreateUserWizard> |
The PasswordRecovery control emails the password information to the user, provided they correctly enter the user name and the password answer. Upon success, the information is emailed automatically. This requires an SMTP account to send email through. This article renders the control, but no SMTP account is specified. You can add one using the ASP.NET Configuration tool.
|
<asp:PasswordRecovery ID="PasswordRecovery1" Runat="server" BackColor="#EFF3FB" Font-Names="Verdana" Font-Size="0.8em" BorderStyle="Solid" BorderPadding="4" BorderColor="#B5C7DE" BorderWidth="1px"> <TitleTextStyle Font-Size="0.9em" Font-Bold="True" BackColor="#507CD1" ForeColor="White"></TitleTextStyle> <TextBoxStyle Font-Size="0.8em"></TextBoxStyle> <InstructionTextStyle Font-Italic="True" Font-Size="0.8em" ForeColor="Black"></InstructionTextStyle> <LabelStyle Font-Size="0.8em"></LabelStyle> <SuccessTextStyle Font-Size="1.2em" Font-Bold="True" ForeColor="#507CD1"></SuccessTextStyle> <HyperLinkStyle Font-Size="0.8em"></HyperLinkStyle> <SubmitButtonStyle Font-Names="Verdana" Font-Size="0.8em" BorderStyle="Solid" BorderWidth="1px" BorderColor="#507CD1" BackColor="White" ForeColor="#284E98"></SubmitButtonStyle> <FailureTextStyle Font-Size="0.8em" ForeColor="#FF0000"></FailureTextStyle> </asp:PasswordRecovery> |
The ChangePassword control is very similar to the PasswordRecovery and CreateUserWizard control. No coding is needed for this control to work; it just needs a valid membership provider.
|
<asp:ChangePassword ID="ChangePassword1" Runat="server" BackColor="#EFF3FB" Font-Names="Verdana" Font-Size="0.8em" BorderStyle="Solid" BorderPadding="4" BorderColor="#B5C7DE" BorderWidth="1px"> <CancelButtonStyle Font-Names="Verdana" Font-Size="0.8em" BorderStyle="Solid" BorderWidth="1px" BorderColor="#507CD1" BackColor="White" ForeColor="#284E98"></CancelButtonStyle> <LabelStyle Font-Size="0.8em"></LabelStyle> <FailureTextStyle Font-Size="0.8em" ForeColor="#FF0000"></FailureTextStyle> <SuccessTextStyle Font-Size="0.8em"></SuccessTextStyle> <ChangePasswordButtonStyle Font-Names="Verdana" Font-Size="0.8em" BorderStyle="Solid" BorderWidth="1px" BorderColor="#507CD1" BackColor="White" ForeColor="#284E98"></ChangePasswordButtonStyle> <ContinueButtonStyle Font-Names="Verdana" Font-Size="0.8em" BorderStyle="Solid" BorderWidth="1px" BorderColor="#507CD1" BackColor="White" ForeColor="#284E98"></ContinueButtonStyle> <TitleTextStyle Font-Size="0.9em" Font-Bold="True" BackColor="#507CD1" ForeColor="White"></TitleTextStyle> <HyperLinkStyle Font-Size="0.8em"></HyperLinkStyle> <PasswordHintStyle Font-Italic="True" Font-Size="0.7em" ForeColor="#507CD1"></PasswordHintStyle> <TextBoxStyle Font-Size="0.8em"></TextBoxStyle> <InstructionTextStyle Font-Italic="True" Font-Size="0.8em" ForeColor="Black"></InstructionTextStyle> </asp:ChangePassword> |
I won't be dealing with the configuration of the web site through the ASP.NET configuration utility (under the Web Site menu option). I setup the web site to use the AspNetAccessProvider provider for retaining Membership and Role information. The whole process is straight-forward. For this application, I included two roles, Administrators and Users. I also have two users to access the application:
| User ID | Password | Roles |
|---|---|---|
| mlemieux | penguins | Administrators, Users |
| dletterman | lateshow | Users |
Login with each account and access the site. With administrative-privileges, the user should have complete access. Users should have access to every feature in the example site except for the admin page.
The downloadable project is a simple application using the Login controls. It uses a master page (site.master) that has the Login and PasswordRecovery controls in a right sidebar. In addition, when the user logs into the site, a LoginView hides the Login control and shows a settings window that has a welcoming message for the user (using the LoginName control) and a LoginStatus control. In this scenario, the Login control is only available when the user is anonymous, and the LoginStatus control only renders the logoff link when the user has logged in to the application. The following code is from the master page:
|
<asp:LoginView ID="lvwLogin" Runat="server"> <LoggedInTemplate> <asp:LoginName ID="lgnName" Runat="server" FormatString="Welcome {0}" /><br /> <asp:LoginStatus ID="lstLogin" Runat="server" /><br /> <asp:HyperLink ID="lnkChangePassword" Runat="server" NavigateUrl="~/changepw.aspx">Change Password</asp:HyperLink> <br /> <br /> <asp:contentplaceholder id="plcUserSettings" runat="server"></asp:contentplaceholder> </LoggedInTemplate> <AnonymousTemplate> <asp:Login ID="lgnLogin" Runat="server" CreateUserUrl="~/createuser.aspx" CreateUserText="Create a New Account" UserNameLabelText="User ID:" BorderStyle="Solid" BorderWidth="1px" BorderColor="#B5C7DE" BorderPadding="4" BackColor="#EFF3FB" ForeColor="#333333" Font-Names="Verdana" Font-Size="0.8em"> <InstructionTextStyle Font-Italic="True" Font-Size="0.8em" ForeColor="Black"></InstructionTextStyle> <CheckBoxStyle Font-Size="0.8em"></CheckBoxStyle> <TextBoxStyle Font-Size="0.8em"></TextBoxStyle> <LabelStyle Font-Size="0.8em"></LabelStyle> <TitleTextStyle Font-Size="0.9em" Font-Bold="True" BackColor="#507CD1" ForeColor="White"></TitleTextStyle> <HyperLinkStyle Font-Size="0.8em"></HyperLinkStyle> <SubmitButtonStyle Font-Names="Verdana" Font-Size="0.8em" BorderStyle="Solid" BorderWidth="1px" BorderColor="#507CD1" BackColor="White" ForeColor="#284E98"></SubmitButtonStyle> <FailureTextStyle Font-Size="0.8em" ForeColor="#FF0000"></FailureTextStyle> </asp:Login> </AnonymousTemplate> </asp:LoginView> <asp:PasswordRecovery ID="PasswordRecovery1" Runat="server" BackColor="#EFF3FB" Font-Names="Verdana" Font-Size="0.8em" BorderStyle="Solid" BorderPadding="4" BorderColor="#B5C7DE" BorderWidth="1px"> <TitleTextStyle Font-Size="0.9em" Font-Bold="True" BackColor="#507CD1" ForeColor="White"></TitleTextStyle> <TextBoxStyle Font-Size="0.8em"></TextBoxStyle> <InstructionTextStyle Font-Italic="True" Font-Size="0.8em" ForeColor="Black"></InstructionTextStyle> <LabelStyle Font-Size="0.8em"></LabelStyle> <SuccessTextStyle Font-Size="1.2em" Font-Bold="True" ForeColor="#507CD1"></SuccessTextStyle> <HyperLinkStyle Font-Size="0.8em"></HyperLinkStyle> <SubmitButtonStyle Font-Names="Verdana" Font-Size="0.8em" BorderStyle="Solid" BorderWidth="1px" BorderColor="#507CD1" BackColor="White" ForeColor="#284E98"></SubmitButtonStyle> <FailureTextStyle Font-Size="0.8em" ForeColor="#FF0000"></FailureTextStyle> </asp:PasswordRecovery> |
The page that contains the CreateUserWizard control (shown above and in createuser.aspx) is linked to from the Login control. This control has a CreateUserUrl property that links to this page, allowing the user to create a new user account. No coding is needed for this page, except to add the user to the default Users role:
|
Partial Class CreateUserPage Private Sub cuzNewUser_CreatedUser(ByVal sender As Object, ByVal e As System.EventArgs) Handles cuzNewUser.CreatedUser 'Add the user to the Users role by default Roles.AddUserToRole(cuzNewUser.UserName, "Users") End Sub End Class |
The sidebar has a link to an article page, named "See My Article". The user must be logged into the site to view it, which this is filtered using the LoginView control. The user can login to access the article through the Login control on the right sidebar. When logging in, the page will refresh and the article is shown.
|
<asp:LoginView ID="LoginView1" Runat="server"> <AnonymousTemplate> Please log into the web site to gain access to the template. </AnonymousTemplate> <LoggedInTemplate> This is the article that you have full permissions to read, because you logged into the web site. </LoggedInTemplate> </asp:LoginView> |
The last page, an administrators-only page, is a simple page that uses a GridView for displaying a list of user accounts. The administrator account must be used; otherwise, a message is rendered stating that the page can't be accessed. The content of the page is shown below:
|
<asp:GridView ID="GridView1" Runat="server" Visible="false"></asp:GridView> <asp:Label ID="lblMessage" Runat="server" Visible="true">You do not have permissions for this function.</asp:Label> |
The Page_Load method checks the user account of the logged in user, through the Membership's GetUser method. If the user isn't logged in, nothing (or null in C#) is returned. The method supports a single Boolean parameter specifying whether to update the user’s last login date in the Access database. A MembershipUser object is returned, which has a UserName property for the name of the user who logged into the site. The GetAllUsers() method is handy when trying to create an administrative application. It returns numerous details about the user, as you will see when you run the example project.
The Roles object supports role-checking through the IsUserInRole method. The Boolean value returned from this method specifies that the user is or isn’t in the desired role. If the user is not an administrator, the Gridview is hidden, and the label is shown. If an administrator, the reverse is true, and all of the user details are viewable.
|
Partial Class admin_aspx Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load If (Not Page.IsPostBack) Then If (Not IsNothing(Membership.GetUser)) Then If (Roles.IsUserInRole(Membership.GetUser(True).UserName, "Administrators")) Then Dim coll As MembershipUserCollection = Membership.GetAllUsers() GridView1.DataSource = coll GridView1.DataBind() GridView1.Visible = True lblMessage.Visible = False End If End If End If End Sub End Class |
This is a simple example of login capabilities. Again the very nice feature of these new controls is the amount of code that doesn't need to be written for all of this to work seamlessly. The framework supports a limited amount of providers (Access and SQL Server); however, for other needs, a custom provider can be written. In later articles, the Membership and Role objects will be detailed further, and I'll delve into the controls in this article with more depth.
You may download the code here.