ServerSideValidationExtender and DropDownList

Topics: Web Client Software Factory
Jul 2, 2009 at 3:49 PM

I am having a problem using a ServerSideValidationExtender with a propertyproxyvalidator on a dropdownlist.  I am trying to make the dropdown a required field by using a DomainValidator.  I have the domainvalidator's domain property set to -1 and the negated property to "True".  The validation always fails when using a dropdown though.  Is it not possible to use a ServerSideValidationExtender with a dropdown?

 <asp:DropDownList ID="ddlAction" runat="server">
    <asp:ListItem Value="-1" Text="--Pick one--"></asp:ListItem>
    <asp:ListItem Value="A" Text="Add"></asp:ListItem>
    <asp:ListItem Value="D" Text="Delete"></asp:ListItem>
    <asp:ListItem Value="U" Text="Update"></asp:ListItem>
</asp:DropDownList>

<val:PropertyProxyValidator ID="valDropDown" runat="server" ControlToValidate="ddlAction" PropertyName="Action" RulesetName="Default" SourceTypeName="MyClass" />

<valExt:ServerSideValidationExtender ID="valReasonExtender" runat="server" TargetControlID="valDropDown" />

Developer
Jul 3, 2009 at 9:01 PM

Hi wc,

 

I have been able to reproduce the issue you mention. Below you can find the reason of the problem and a possible workaround.

Debugging the DoValidate method of the validator I found that the problem is that the objectToValidate parameter (that is the value which is tested for validity) is not updating. So, the method is always checking if "-1" is a valid value and returning false as you explained.

 

Digging into the ServerSideValidationExtender I found the problem root. The ServerSideValidationExtender control relies on the BaseValidator.GetValidationProperty and PropertyDescriptor.SetValue methods to update the control's property value. In the case of DropDownList controls, the PropertyDescriptor returned by GetValidationProperty method is a read-only property and thus SetValue will not set the control's property value:

                               private static void SetControlValidationValue(Control validator, string controlName, string value)

{

    Guard.ArgumentNotNull(validator, "validator");

 

    Control component = validator.NamingContainer.FindControl(controlName);

    if (component == null)

    {

        string message = string.Format(CultureInfo.CurrentCulture, Resources.CannotFindControlToValidate, controlName);

        throw new InvalidOperationException(message);

    }

    PropertyDescriptor validationProperty = BaseValidator.GetValidationProperty(component); // for DropDownList control, this returns a readOnly Property

    if (validationProperty == null)

    {

        string message = string.Format(CultureInfo.CurrentCulture, Resources.NoValidationProperty, controlName);

        throw new InvalidOperationException(message);

    }

    validationProperty.SetValue(component, value);  // this will not change the value for DropDownList controls

 

NOTE:  you can find this code in the AjaxControlToolkit.WCSFExtensions.ServerSideValidationExtender class extracting the WCSF source that comes with the Software Factory. You can check Extending the Application Blocks for more details.

 

Workaround

To workaround for this issue you will need to modify the ServerSideValidationExtender  class code to take this scenario into account.

You can add the following code to the end of the SetControlValidationValue method to set the SelectedValue when the control is a DropDownList:

 

// If the control is a DropDownList, set the SelectedValue

DropDownList dropDownList = component as DropDownList;

if (dropDownList != null)

{

    dropDownList.SelectedValue = value;

}

                NOTE: You will need to recompile the AjaxControlToolkit.WCSFExtensions project and reference the newly generated assembly in your project.

 

Hope it helps!

 

Matias Bonaventura

http://blogs.southworks.net/matiasb

Jul 6, 2009 at 1:59 PM

Thanks, Matias. 

Sep 24, 2009 at 8:53 AM

The same applies to RadioButtonList.

Instead of Matias patch I suggest following

         

if (component is DropDownList)
{
DropDownList dropDownList = component as DropDownList;
                dropDownList.SelectedValue = value;
            }
            else if (component is RadioButtonList)
            {
                RadioButtonList radioButtonList = component as RadioButtonList;
                radioButtonList.SelectedValue = value;
            }