简体   繁体   中英

asp:RequiredFieldValidator does not validate hidden fields

It seems that ASP.NET validators do not validate hidden fields. I get messages like this:

Control 'hiddenField' referenced by the ControlToValidate property of 'hiddenFieldValidator' cannot be validated.

I have an <asp:HiddenField> in my page which gets filled client side with some value. I need this to be present once on the server so I added a RequiredFieldValidator to it.

And it does not work!

As I see it, as a workaround, I can:

1. use a custom validator and not tie it to the hidden field, just call a method on OnServerValidate ;

2. Use a <asp:TextBox> with a CSS style display:none and it should work.

But I want to make sure I am not missing something here. Is it possible or not to validate a hidden field in the same way as the other text fields? O maybe a third, more elegant option?

TIA!

@Peter's answer got me thinking, what does ControlPropertiesValid actually check??

Looking at the MSDN topic it looks for, among other things, the ValidationPropertyAttribute .. Hhmm, so if we just derive from HiddenField and decorate the new class with ValidationPropertyAttribute set to Value (for my purposes) then 'everything just works'. And it does.

using System.Web.UI;
using System.Web.UI.WebControls;

namespace Partner.UserControls {
    [ValidationProperty("Value")]
    public class HiddenField2 : HiddenField {
    } // nothing else required other than ValidationProperty
}

Usage - make sure you register the assembly containing the control:

<%@ Register Assembly="MyApp" Namespace="MyApp.Controls" TagPrefix="sw" %>

And in your Page/UserControl content:

<sw:HiddenField2 ID="hidSomeImportantID" runat="server" />

All validators will work with this. The added benefit is that if you (like me) are using a custom validation function you can easily evaluate the HiddenField2.Value because it is contained in the args.Value field (on server side this is ServerValidateEventArgs ).

Here is the workaround I came up with, because unfortunately I couldn't find any reliable way to validate using the RequiredFieldValidator OR the CustomValidator out of the box. If you leave the ControlToValidate property empty it yells at you. All you have to do is create a custom control like the one below:

public class HiddenFieldValidator : RequiredFieldValidator
{
    protected override bool ControlPropertiesValid()
    {
        return true;
    }
}

By overriding the properties valid check so that it always returns true it no longer cares that you are using a HiddenField and it will pull the value out of it and verify without issue.

Just as the exception message you're getting says, it seems HiddenField controls can't be targeted by the standard validation controls directly. I would go with the CustomValidator workaround.

This is a response to the solution by Scotty.NET. I just don't have enough reputation to reply.

+1 to Scotty.NET!

For those of us who don't know enough about .NET and compiling and such, this may help simplify usage of his answer for someone else.

I wanted to make use of it in a website using Visual Web Developer 2010 Express:

1) I saved the derived HiddenField2 in /App_Code as HiddenField2.cs, with one change --> namespace Controls

2) Then, to register the control:

a) On the page, <%@ Register Assembly="App_Code" Namespace="Controls" TagPrefix="local" %>

b) In web.config, within system.web > pages > controls, <add tagPrefix="local" namespace="Controls" assembly="App_Code" />

3) And, finally, of course, refer to it as <local:HiddenField2...> .

It does make for funky code coloring. Probably fairly easy to improve the namespace to handle that. Works wonderfully for me in my local environment; guess I don't know it won't have problems on a live server.

Additional reference: extending asp.net control in the website project

To expand on @Anders' solution, with a CustomValidator approach, you can very easily grab the value of a standard HiddenField control by first finding the control, casting it, and then using its UniqueID to look its value up in the Page.Request.Form[] .


Example 1: Improving the Compare Validator

This example may be a bit more local to your implementation. The below is an improved version of the CompareValidator.EvaluateIsValid() method call, in order to add support for validating HiddenField controls. Note that this technique can be applied to any validator, instead of wrapping the HiddenField in a custom control, but that the ControlPropertiesValid method should also be overriden to recognize and return true in the presence of a HiddenField .

...

private new string GetControlValidationValue(string id)
{
    var control = this.NamingContainer.FindControl(id); 
    if (control != null)
    {
        if (control is HiddenField) 
        {
            return Page.Request.Form[((HiddenField)control).UniqueID];
        } 
        else 
        {
            return base.GetControlValidationValue(id);
        }
    }
}

protected override bool EvaluateIsValid()
{   
    // removed 'base.' from the call to 'GetControlValidationValue'
    string controlValidationValue = GetControlValidationValue(base.ControlToValidate);
    if (controlValidationValue.Trim().Length == 0)
    {
        return true;
    }
    bool flag = (base.Type == ValidationDataType.Date) && !this.DetermineRenderUplevel();
    if (flag && !base.IsInStandardDateFormat(controlValidationValue))
    {
        controlValidationValue = base.ConvertToShortDateString(controlValidationValue);
    }
    bool cultureInvariantRightText = false;
    string date = string.Empty;
    if (this.ControlToCompare.Length > 0)
    {
        //same as above
        date = GetControlValidationValue(this.ControlToCompare);
        if (flag && !base.IsInStandardDateFormat(date))
        {
            date = base.ConvertToShortDateString(date);
        }
    }
    else
    {
        date = this.ValueToCompare;
        cultureInvariantRightText = base.CultureInvariantValues;
    }
    return BaseCompareValidator.Compare(controlValidationValue, false, date, cultureInvariantRightText, this.Operator, base.Type);
}

...    


Example 2: Custom Dynamic Validator

This example is a bit more complicated than the first one. I regularly use custom dynamic validators that are enabled or disabled based on the value of another control on the page (eg, if that box is checked then this textbox is required; otherwise it does not need to be validated). One such validator is my DynamicRequiredFieldValidator , which inherits from the built-in RequiredFieldValidator . The dynamic validator has two custom attributes, ControlThatEnables and ControlValueThatEnables , that are used to decide whether or not the validator should be turned on. The below is a snippet from the method that determines whether or not the validator should be enabled, but note that, as above, this same technique can be applied to validating a HiddenField without the need to wrap it in a custom control.

...

var enablingControl = this.NamingContainer.FindControl(ControlThatEnables); 
if (enablingControl != null) 
{
    if (enablingControl is HiddenField)
    {
        var hfValue = Page.Request.Form[((HiddenField)enablingControl).UniqueID];
        isValidatorEnabled = hfValue == ControlValueThatEnables;
    }
}

...


Final Thoughts

The implementation decision is ultimately up to you, as the developer, but my preference is to wrap existing validators in custom controls, rather than to wrap things like HiddenFields , TextBoxes , DropDownLists , etc. in custom controls. I have two main reason for preferring this solution: (1) wrapping the validators take only a few minutes more than just adding the ValidationProperty , but provides significantly more flexibility and opportunity for further improvement of .NET validaton, eg one could point the FindControl calls to some custom method that searches for the desired control ID in the current NamingContainer (default) and then expands the search to the outer Page or the NamingContainer 's parent if the control was not found; (2) IMHO if one is trying to improve validation, it is cleaner to make improvements to validation, and, contrarily, if one is trying to improve a WebControl , it is cleaner to make improvements to the WebControl .

I completely respect @Scotty's solution, and will be the first to admit that if it is the only change to be made, then his solution will save you 5 minutes more than this one. IMHO however, @Anders' is likely to be a better choice, in the long run.

I'd go with a CustomValidator client side

<script type="text/javascript">
function myMethod(source, args) {
    args.IsValid = document.getElementById("<%= myValue.ClientID %>").value != '';
}
</script>

<asp:HiddenField ID="myValue" runat="server" />
<asp:CustomValidator runat="server" ClientValidationFunction="myMethod" 
                     ErrorMessage="Value missing!" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM