I have a website that I created that uses an ASP.NET Login control to assist in user authentication on the site. I've used the Login control on other sites and it's provides a very convenient mechanism for authenticating a user. On this site particular site I have the Login control contained within a wrapper control (which I called LoginBox). Due to the nature of this site, the LoginBox does not exist on the page in the ASP.NET HTML markup but rather is added to the page dynamically. As such I don't have the convenience of editing the HTML markup of the asp:Login control directly but must interact with it programmatically.
The Login control provides several properties through which I can achieve a nice look and feel. It contains child controls for the title, labels, textboxes, required field validators, checkboxes, and buttons. Each of these can be customized via CSS styles or by directly assigning values to the controls' properties.
In this particular site I needed to extend the appearance of the control, adding some textboxes to the control. At first this wasn't very intuitive, but I'll show you that it is, in fact, quite easy to achieve. You can easily add fields to the control (e.g., a 'verify password' field, an 'email' field, a CAPTCHA control, etc) by customizing the LayoutTemplate of the Login control.
Were I to have had the control in the HTML markup of my page this would be a piece of cake. Note, via the designer, you can simply click the Login control's smart tag and click “Convert to Template“ or create it manually:
<asp:Login runat="server" id="login">
<LayoutTemplate>
<!-- HTML template here -->
</LayoutTemplate>
</asp:Login>
However, as the control is being generated entirely in code, the template must be created programmatically. As a bare minimum, you need two controls in your template that implement the ITextControl interface for the control to render; otherwise, you'll get an exception (TextBoxes will suffice or any control you create that implements that interface). These controls are UserName and Password. I recommend adding the login button as well (Button, LinkButton, or ImageButton) with a CommandName set to “Login“. Using a template, you can fully customize the look and feel of the output. Note, that when you go the route of creating a custom template, you are solely responsible for the output. In other words, you're completely replacing the output that the Login control generates; if you want field validators, you need to add them.
// somewhere in the page (e.g., Page.Init)
Login login = new Login();
login.LayoutTemplate = new LoginTemplate();
Controls.Add(login);
internal class LoginTemplate : ITemplate {
public void InstantiateIn(Control container) {
TextBox txtUserName = new TextBox();
txtUserName.ID = "UserName";
container.Controls.Add(txtUserName);
TextBox txtPassword = new TextBox();
txtPassword.ID = "Password";
container.Controls.Add(txtPassword);
ImageButton btnLogin = new ImageButton();
btnLogin.ID = "LoginButton";
btnLogin.ImageUrl = "~/images/LoginButton.gif";
btnLogin.CommandName = "Login";
container.Controls.Add(btnLogin);
}
}
With this, I have an extremely boring-looking Login control, but you get the idea.
When the page is posted back, you can easily retrieve the contents of any control you added to the template by calling the .FindControl() method, referencing it by name:
string emailAddress = ( ( TextBox )login.FindControl("txtEmail") ).Text;