Live Chat Programs

March 25, 2008

A Quick Fix for the Validator SetFocusOnError Bug

Filed under: Live Chat software
The ASP.NET validators have this nice property called “SetFocusOnError” that is supposed to set the focus to the first control that failed validation. This all works great until your validator control is inside a naming container. I ran into this recently when using validators in a DetailsView. Take this simple example:

Also see: SIGPLAN Workshop on Undergraduate Programming Language Curriculum

<%@ Page Language=”C#” %>
<script runat=”server”>
 protected void Page_Load(object sender, EventArgs e)
 {
 if (!IsPostBack)
 DataBind();
 }
</script>
<!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></title>
</head>
<body>
<form id=”_frm” runat=”server”>
 <asp:DetailsView
 ID=”dv1″
 DefaultMode=”Edit”
 DataSource=’<%# new object[1] %>’
 runat=”server”
 >
 <Fields>
 <asp:TemplateField HeaderText=”First Name:”>
 <EditItemTemplate>
 <asp:TextBox ID=”FirstNameTextBox” runat=”server” />
 <asp:RequiredFieldValidator
 ID=”FirstNameValidator1″
 ControlToValidate=”FirstNameTextBox”
 ErrorMessage=”First name is required.”
 Display=”Dynamic”
 EnableClientScript=”false”
 SetFocusOnError=”true”
 ValidationGroup=”bug”
 Text=”*”
 runat=”server”
 />
 </EditItemTemplate>
 </asp:TemplateField>
 </Fields>
 <FooterTemplate>
 <asp:ValidationSummary
 ID=”vs1″
 DisplayMode=”List”
 ValidationGroup=”bug”
 runat=”server”
 />
 <asp:Button
 ID=”Button1″
 Text=”Post Back”
 ValidationGroup=”bug”
 runat=”server”
 />
 </FooterTemplate>
 </asp:DetailsView>
</form>
</body>
</html>

If you run this page and do a view source you’ll see that the FirstNameTextBox gets rendered like this:

<input name=”dv1$FirstNameTextBox” type=”text” id=”dv1_FirstNameTextBox” />
If you just do a post back without entering a value to cause the validator to fail it will output this line of java script in an attempt to set the focus to the invalid element:

Also see: Win friends and influence your team

Also see: Binding to .NET Frameworks Assemblies

WebForm_AutoFocus(‘FirstNameTextBox’);

See anything wrong with this? It would seem that the validators just use the string value you typed in for the ControlToValidate property rather than doing a FindControl and using the UniqueID. This is exactly what happens and I verified it with reflector. The Validate method on BaseValidator does this:
if ((!this.IsValid && (this.Page != null)) && this.SetFocusOnError)
{
 this.Page.SetValidatorInvalidControlFocus(this.ControlToValidate);
}

If you follow the call to SetValidatorInvalidControlFocus you’ll see that it never resolves the full UniqueID of the control that its going to set focus to.
 
Ok, so this sucks. How do I work around it. My solution was to simply ditch using the SetFocusOnError property and implement the focus logic myself which is actually pretty easy. I overrode Validate method on my Page like this:
Live Person Software: Just one single click and your website visitors are getting into instant message chatting with you.

Also see: Microformats are like RFID tags for the Web

Also see: Startup, Shutdown and related matters

Also see: When Are Two Algorithms the Same?

Also see: ReflectionTypeLoadException

Also see: JSR-203 more New I/O APIs - NIO.2

public override void Validate(string group)
{
 base.Validate(group);
	
 // find the first validator that failed
 foreach (IValidator validator in GetValidators(group))
 {
 if (validator is BaseValidator && !validator.IsValid)
 {
 BaseValidator bv = (BaseValidator)validator;
	
 // look up the control that failed validation
 Control target =
 bv.NamingContainer.FindControl(bv.ControlToValidate);
	
 // set the focus to it
 if (target != null)
 target.Focus();
	
 break;
 }
 }
}
If your using C# 3 this is even easier using LINQ:
public override void Validate(string group)
{
 base.Validate(group);
	
 // get the first validator that failed
 var validator = GetValidators(group)
.OfType<BaseValidator>()
.FirstOrDefault(v => !v.IsValid);
	
 // set the focus to the control
 // that the validator targets
 if (validator != null)
 {
 Control target = validator
.NamingContainer
.FindControl(validator.ControlToValidate);
	
 if (target != null)
 target.Focus();
 }
}

Help Desk Software: for your business. Java Custom Software Soulutions and Service.

Also see: Startup, Shutdown and related matters

Also see: Binding to .NET Frameworks Assemblies

Also see: Silverlight 2 Beta 1 Cross Domain Bug

I hope this saves someone the headache of tracking this down.

http://weblogs.asp.net/dfindley/archive/2007/06/29/a-quick-fix-for-the-validator-setfocusonerror-bug.aspx

Comments »

The URI to TrackBack this entry is: http://thelivechatsoftware.blogsome.com/2008/03/25/a-quick-fix-for-the-validator-setfocusonerror-bug-2/trackback/

No comments yet.

RSS feed for comments on this post.

Leave a comment

Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>



Anti-spam measure: please retype the above text into the box provided.

Get free blog up and running in minutes with Blogsome
Theme designed by Jay of onefinejay.com