Hi, I am writing a Login composite control which includes UserName and password textboxes and two RequiredFieldValidators. The problem I have is that when the control is rendered on the page one of the validators triggers by itself and display the error message
before any user input. Another bizarre behaviour is that the error message displayed is the one for the password in the position where the error message for the UserName validator should be. In the following HTML code you can see that the part "Password required"
message is right under the UserName textbox:
I can't find anything wrong with the code I wrote. I also tried to disable validation through client script (EnableClientScript = False), but it didn't help. Any idea of what may be wrong? Here is the code:
Imports System.Web.UI
Imports System.Web.Security
Imports System.Web.UI.WebControls
Imports Informa.Services.DataServices
Imports Informa.Module.Community.Business
Public Class Login2 : Inherits Control
Private userNameBox As TextBox
Private userValidator As RequiredFieldValidator
Private passwordBox As TextBox
Private passwordValidator As RequiredFieldValidator
Private autoLogin As CheckBox
Private loginButton As Button
Private Const HtmlNewLine As String = " "
Protected Overrides Sub CreateChildControls()
userNameBox = New TextBox
With userNameBox
.ID = "UserName"
.MaxLength = 10
.Width = Unit.Pixel(145)
End With
userValidator = New RequiredFieldValidator
With userValidator
.ControlToValidate = "UserName"
.Display = ValidatorDisplay.Dynamic
.
.ErrorMessage = HtmlNewLine & ResourcesManager.UserNameRequired(True) & HtmlNewLine
End With
passwordBox = New TextBox
With passwordBox
.ID = "Password"
.MaxLength = 10
.TextMode = TextBoxMode.Password
.Width = Unit.Pixel(145)
End With
passwordValidator = New RequiredFieldValidator
With userValidator
.ControlToValidate = "Password"
.Display = ValidatorDisplay.Dynamic
.EnableClientScript = True
.ErrorMessage = HtmlNewLine & ResourcesManager.PasswordRequired(True) & HtmlNewLine
End With
autoLogin = New CheckBox
With autoLogin
.TextAlign = TextAlign.Right
.Checked = True
.Text = ResourcesManager.AutomaticLogin(True)
End With
loginButton = New Button
With loginButton
.ID = "LoginButton"
.Width = Unit.Percentage(100)
.Text = ResourcesManager.Login(True)
AddHandler .Click, AddressOf LoginButton_Click
End With
End Sub
Protected Overrides Sub Render(ByVal writer As HtmlTextWriter)
Me.EnsureChildControls()
With writer
.AddAttribute(HtmlTextWriterAttribute.Id, "Login")
.RenderBeginTag(HtmlTextWriterTag.Div)
.RenderBeginTag(HtmlTextWriterTag.H3)
.Write(ResourcesManager.ForumLogin(True))
.RenderEndTag() ' close H3
.Write(ResourcesManager.UserName(True))
userNameBox.RenderControl(writer)
userValidator.RenderControl(writer)
.Write(ResourcesManager.Password(True))
passwordBox.RenderControl(writer)
passwordValidator.RenderControl(writer)
loginButton.RenderControl(writer)
autoLogin.RenderControl(writer)
.Write(HtmlNewLine)
.AddAttribute(HtmlTextWriterAttribute.Href, GlobalUrls.UrlRegister())
.RenderBeginTag(HtmlTextWriterTag.A)
.Write(ResourcesManager.CreateNewAccount(True))
.RenderEndTag() ' close the link
.Write(HtmlNewLine)
.AddAttribute(HtmlTextWriterAttribute.Href, GlobalUrls.UrlForgotPassword())
.RenderBeginTag(HtmlTextWriterTag.A)
.Write(ResourcesManager.ForgotPasswordShort(True))
.RenderEndTag() ' close the link
.RenderEndTag() ' close div
End With
End Sub
Public Sub LoginButton_Click(ByVal sender As Object, ByVal e As EventArgs)
Page.Validate()
If Page.IsValid Then
Dim userName As String = userNameBox.Text.Trim
Dim pass As String = passwordBox.Text.Trim
If Users.ValidUser(userName, pass) = DatabaseResult.RecordFound Then
FormsAuthentication.SetAuthCookie(userName, autoLogin.Checked)
Page.Response.Redirect(GlobalUrls.UrlHome(), True)
End If
End If
End Sub
End Class
You have written this control incorrectly. Instead of rendering each control in the Render method, in the CreateChildControl method, add each control to the Login2.Controls property. Don't override Render at all. The default Render method will output your controls.
To add the start and end <div> tags, add LiteralControl objects with the desired strings at the beginning and end of the Controls collection. By writing it the way you have, each Validator is run through a Render method without getting prepared (their OnPreRender
method isn't called. That sets up the validator correctly.) Putting them in the Controls collection assures you that they will get their OnPreRender method called at the correct time.
--- Peter Blum
Creator of Peter's Data Entry Suite (formerly Professional Validation And More and Peter's Date Package) and Peter's Polling Package
www.PeterBlum.com
Peter, thanks for the answer. Although I am not too happy to lose the convenience of using HtmlTextWriter class, I have followed your advice and rewrote the code the following way:
Imports System.Web.UI
Imports System.Web.Security
Imports System.Web.UI.WebControls
Imports Informa.Services.DataServices
Imports Informa.Module.Business
Imports Informa.Module.Components
Imports Informa.Module.Configuration
Public Class Login2 : Inherits Control
Private userNameBox As TextBox
Private userValidator As RequiredFieldValidator
Private passwordBox As TextBox
Private passwordValidator As RequiredFieldValidator
Private autoLogin As CheckBox
Private loginButton As Button
Private Const HtmlNewLine As String = "
"
Protected Overrides Sub CreateChildControls()
userNameBox = New TextBox
With userNameBox
.ID = "UserName"
.MaxLength = 10
.Width = Unit.Pixel(145)
End With
passwordBox = New TextBox
With passwordBox
.ID = "Password"
.MaxLength = 10
.TextMode = TextBoxMode.Password
.Width = Unit.Pixel(145)
End With
userValidator = New RequiredFieldValidator
With userValidator
.ControlToValidate = "UserName"
.Display = ValidatorDisplay.Dynamic
.EnableClientScript = True
.ErrorMessage = HtmlNewLine & ResourcesManager.UserNameRequired(True) & HtmlNewLine
End With
passwordValidator = New RequiredFieldValidator
With userValidator
.ControlToValidate = "Password"
.Display = ValidatorDisplay.Dynamic
.EnableClientScript = True
.ErrorMessage = HtmlNewLine & ResourcesManager.PasswordRequired(True) & HtmlNewLine
End With
autoLogin = New CheckBox
With autoLogin
.TextAlign = TextAlign.Right
.Checked = True
.Text = ResourcesManager.AutomaticLogin(True)
End With
loginButton = New Button
With loginButton
.ID = "LoginButton"
.Width = Unit.Percentage(100)
.Text = ResourcesManager.Login(True)
AddHandler .Click, AddressOf LoginButton_Click
End With
With MyBase.Controls
.Add(New LiteralControl("<div id=""Login"">"))
.Add(New LiteralControl("
"))
.Add(New LiteralControl(ResourcesManager.ForumLogin(True)))
.Add(New LiteralControl("
"))
.Add(New LiteralControl(ResourcesManager.UserNameLabel(True)))
.Add(userNameBox)
.Add(userValidator)
.Add(New LiteralControl(ResourcesManager.Password(True)))
.Add(passwordBox)
.Add(passwordValidator)
.Add(loginButton)
.Add(autoLogin)
.Add(New LiteralControl(HtmlNewLine))
.Add(New LiteralControl("" & ResourcesManager.ForgotPasswordShort(True) & ""))
.Add(New LiteralControl("</div>"))
End With
End Sub
Public Sub LoginButton_Click(ByVal sender As Object, ByVal e As EventArgs)
Page.Validate()
If Page.IsValid Then
Dim userName As String = userNameBox.Text.Trim
Dim pass As String = passwordBox.Text.Trim
If Users.ValidUser(userName, pass) = DatabaseResult.RecordFound Then
FormsAuthentication.SetAuthCookie(userName, autoLogin.Checked)
Page.Response.Redirect(GlobalUrls.GetInstance.UrlHome(), True)
End If
End If
End Sub
End Class
Now I get the error: The ControlToValidate property of '' cannot be blank
Stack trace: [HttpException (0x80004005): The ControlToValidate property of '' cannot be blank.] System.Web.UI.WebControls.BaseValidator.ControlPropertiesValid() +105 System.Web.UI.WebControls.BaseValidator.Render(HtmlTextWriter writer) +85 System.Web.UI.Control.RenderControl(HtmlTextWriter
writer) +130 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +72 System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer) +7 System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) +29 System.Web.UI.Control.RenderControl(HtmlTextWriter
writer) +130 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +72 System.Web.UI.Control.Render(HtmlTextWriter writer) +7 System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +130 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
+72 System.Web.UI.HtmlControls.HtmlForm.RenderChildren(HtmlTextWriter writer) +44 System.Web.UI.HtmlControls.HtmlForm.Render(HtmlTextWriter output) +260 System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +130 System.Web.UI.Control.RenderChildren(HtmlTextWriter
writer) +72 System.Web.UI.Control.Render(HtmlTextWriter writer) +7 System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +130 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +72 System.Web.UI.Control.Render(HtmlTextWriter writer) +7 System.Web.UI.Control.RenderControl(HtmlTextWriter
writer) +130 System.Web.UI.Page.ProcessRequestMain() +1912 However, both validators have the ControlToValidate property set with the IDs of the two textboxes. Any idea on what may be wrong? * Marco
Hi Marco, You have an error. Look at: passwordValidator = New RequiredFieldValidator With userValidator It should read: passwordValidator = New RequiredFieldValidator With passwordValidator
--- Peter Blum
Creator of Peter's Data Entry Suite (formerly Professional Validation And More and Peter's Date Package) and Peter's Polling Package
www.PeterBlum.com
Ouch! That was dumb... I should have checked. Thanks, Peter. While we are on the subject of validators, yesterday I have downloaded your VAM controls. I am evalutaing them now, but I am impressed already. You have a fine piece of work there. Ciao, * Marco
Thanks Marco. Drop me an email at support@PeterBlum.com with any questions.
--- Peter Blum
Creator of Peter's Data Entry Suite (formerly Professional Validation And More and Peter's Date Package) and Peter's Polling Package
www.PeterBlum.com
Marco; Thanks for posting all your code. I'm just learning how to make my own composite controls and your code was very helpful. Is it correct to say that there is no way to create a composite control that still is visible at design time in Visual Studio?
Sorry for the late reply, I found your message only today.
No, actually that is not correct. You would need to write a designer to have the custom control visible in the design view of VS. But I am not an expert in writing control designers as I don't bother writing them. As I only develop web applications I never
use the design view. I prefer to work directly on the HTML code. I suggest you do a search for control designers.
GuruBeBop
Member
40 Points
8 Posts
Validator triggers by itself
Dec 14, 2003 11:10 AM|LINK
PLBlum
All-Star
30399 Points
5347 Posts
MVP
Re: Validator triggers by itself
Dec 15, 2003 07:30 PM|LINK
Creator of Peter's Data Entry Suite (formerly Professional Validation And More and Peter's Date Package) and Peter's Polling Package
www.PeterBlum.com
GuruBeBop
Member
40 Points
8 Posts
The ControlToValidate property of '' cannot be blank
Dec 16, 2003 10:59 AM|LINK
Imports System.Web.UI Imports System.Web.Security Imports System.Web.UI.WebControls Imports Informa.Services.DataServices Imports Informa.Module.Business Imports Informa.Module.Components Imports Informa.Module.Configuration Public Class Login2 : Inherits Control Private userNameBox As TextBox Private userValidator As RequiredFieldValidator Private passwordBox As TextBox Private passwordValidator As RequiredFieldValidator Private autoLogin As CheckBox Private loginButton As Button Private Const HtmlNewLine As String = " " Protected Overrides Sub CreateChildControls() userNameBox = New TextBox With userNameBox .ID = "UserName" .MaxLength = 10 .Width = Unit.Pixel(145) End With passwordBox = New TextBox With passwordBox .ID = "Password" .MaxLength = 10 .TextMode = TextBoxMode.Password .Width = Unit.Pixel(145) End With userValidator = New RequiredFieldValidator With userValidator .ControlToValidate = "UserName" .Display = ValidatorDisplay.Dynamic .EnableClientScript = True .ErrorMessage = HtmlNewLine & ResourcesManager.UserNameRequired(True) & HtmlNewLine End With passwordValidator = New RequiredFieldValidator With userValidator .ControlToValidate = "Password" .Display = ValidatorDisplay.Dynamic .EnableClientScript = True .ErrorMessage = HtmlNewLine & ResourcesManager.PasswordRequired(True) & HtmlNewLine End With autoLogin = New CheckBox With autoLogin .TextAlign = TextAlign.Right .Checked = True .Text = ResourcesManager.AutomaticLogin(True) End With loginButton = New Button With loginButton .ID = "LoginButton" .Width = Unit.Percentage(100) .Text = ResourcesManager.Login(True) AddHandler .Click, AddressOf LoginButton_Click End With With MyBase.Controls .Add(New LiteralControl("<div id=""Login"">")) .Add(New LiteralControl("Now I get the error: The ControlToValidate property of '' cannot be blank Stack trace: [HttpException (0x80004005): The ControlToValidate property of '' cannot be blank.] System.Web.UI.WebControls.BaseValidator.ControlPropertiesValid() +105 System.Web.UI.WebControls.BaseValidator.Render(HtmlTextWriter writer) +85 System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +130 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +72 System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer) +7 System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) +29 System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +130 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +72 System.Web.UI.Control.Render(HtmlTextWriter writer) +7 System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +130 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +72 System.Web.UI.HtmlControls.HtmlForm.RenderChildren(HtmlTextWriter writer) +44 System.Web.UI.HtmlControls.HtmlForm.Render(HtmlTextWriter output) +260 System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +130 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +72 System.Web.UI.Control.Render(HtmlTextWriter writer) +7 System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +130 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +72 System.Web.UI.Control.Render(HtmlTextWriter writer) +7 System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +130 System.Web.UI.Page.ProcessRequestMain() +1912 However, both validators have the ControlToValidate property set with the IDs of the two textboxes. Any idea on what may be wrong? * Marco"))
.Add(New LiteralControl(ResourcesManager.ForumLogin(True))) .Add(New LiteralControl(" ")) .Add(New LiteralControl(ResourcesManager.UserNameLabel(True))) .Add(userNameBox) .Add(userValidator) .Add(New LiteralControl(ResourcesManager.Password(True))) .Add(passwordBox) .Add(passwordValidator) .Add(loginButton) .Add(autoLogin) .Add(New LiteralControl(HtmlNewLine)) .Add(New LiteralControl("" & ResourcesManager.ForgotPasswordShort(True) & "")) .Add(New LiteralControl("</div>")) End With End Sub Public Sub LoginButton_Click(ByVal sender As Object, ByVal e As EventArgs) Page.Validate() If Page.IsValid Then Dim userName As String = userNameBox.Text.Trim Dim pass As String = passwordBox.Text.Trim If Users.ValidUser(userName, pass) = DatabaseResult.RecordFound Then FormsAuthentication.SetAuthCookie(userName, autoLogin.Checked) Page.Response.Redirect(GlobalUrls.GetInstance.UrlHome(), True) End If End If End Sub End ClassPLBlum
All-Star
30399 Points
5347 Posts
MVP
Re: The ControlToValidate property of '' cannot be blank
Dec 16, 2003 11:16 PM|LINK
Creator of Peter's Data Entry Suite (formerly Professional Validation And More and Peter's Date Package) and Peter's Polling Package
www.PeterBlum.com
GuruBeBop
Member
40 Points
8 Posts
Re: The ControlToValidate property of '' cannot be blank
Dec 17, 2003 08:28 AM|LINK
PLBlum
All-Star
30399 Points
5347 Posts
MVP
Re: The ControlToValidate property of '' cannot be blank
Dec 18, 2003 07:47 PM|LINK
Creator of Peter's Data Entry Suite (formerly Professional Validation And More and Peter's Date Package) and Peter's Polling Package
www.PeterBlum.com
Blitzkrieg
Member
472 Points
107 Posts
Re: The ControlToValidate property of '' cannot be blank
Oct 21, 2005 09:25 PM|LINK
Todd M. Taylor
GuruBeBop
Member
40 Points
8 Posts
Re: The ControlToValidate property of '' cannot be blank
Oct 30, 2005 11:23 PM|LINK
No, actually that is not correct. You would need to write a designer to have the custom control visible in the design view of VS. But I am not an expert in writing control designers as I don't bother writing them. As I only develop web applications I never use the design view. I prefer to work directly on the HTML code. I suggest you do a search for control designers.
* Marco