简体   繁体   English

asp:RequiredFieldValidator 不验证隐藏字段

[英]asp:RequiredFieldValidator does not validate hidden fields

It seems that ASP.NET validators do not validate hidden fields.似乎 ASP.NET 验证器不验证隐藏字段。 I get messages like this:我收到这样的消息:

Control 'hiddenField' referenced by the ControlToValidate property of 'hiddenFieldValidator' cannot be validated.无法验证由“hiddenFieldValidator”的 ControlToValidate 属性引用的控件“hiddenField”。

I have an <asp:HiddenField> in my page which gets filled client side with some value.我的页面中有一个<asp:HiddenField> ,它在客户端填充了一些值。 I need this to be present once on the server so I added a RequiredFieldValidator to it.我需要它在服务器上出现一次,所以我向它添加了一个RequiredFieldValidator

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 ; 1.使用自定义验证器,不要将其绑定到隐藏字段,只需调用OnServerValidate上的方法;

2. Use a <asp:TextBox> with a CSS style display:none and it should work. 2.使用带有 CSS 样式display:none<asp:TextBox> ,它应该可以工作。

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?? @Peter 的回答让我想到, ControlPropertiesValid实际检查的是什么?

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'.查看MSDN 主题,除其他外,它查找ValidationPropertyAttribute .. 嗯,所以如果我们只是从HiddenField派生并装饰新的 class 并将ValidationPropertyAttribute设置为Value (出于我的目的),那么“一切正常”。 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:在您的 Page/UserControl 内容中:

<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 ).额外的好处是,如果您(像我一样)使用自定义验证 function 您可以轻松评估HiddenField2.Value因为它包含在args.Value字段中(在服务器端,这是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.这是我想出的解决方法,因为不幸的是,我找不到任何可靠的方法来使用RequiredFieldValidator 或开箱即用的CustomValidator 进行验证。 If you leave the ControlToValidate property empty it yells at you.如果您将 ControlToValidate 属性留空,它会对您大喊大叫。 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.通过覆盖属性有效检查,使其始终返回 true,它不再关心您是否使用 HiddenField,它将从中提取值并验证没有问题。

Just as the exception message you're getting says, it seems HiddenField controls can't be targeted by the standard validation controls directly.正如您收到的异常消息所说,标准验证控件似乎不能直接定位HiddenField控件。 I would go with the CustomValidator workaround.我会 go 与CustomValidator解决方法。

This is a response to the solution by Scotty.NET.这是对 Scotty.NET 解决方案的回应。 I just don't have enough reputation to reply.我只是没有足够的声誉来回复。

+1 to Scotty.NET! +1 到 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.对于我们这些对 .NET 和编译等不太了解的人,这可能有助于简化他对其他人的答案的使用。

I wanted to make use of it in a website using Visual Web Developer 2010 Express:我想在使用 Visual Web Developer 2010 Express 的网站中使用它:

1) I saved the derived HiddenField2 in /App_Code as HiddenField2.cs, with one change --> namespace Controls 1) 我将 /App_Code 中的派生 HiddenField2 保存为 HiddenField2.cs,只需进行一次更改 --> namespace Controls

2) Then, to register the control: 2)然后,注册控件:

a) On the page, <%@ Register Assembly="App_Code" Namespace="Controls" TagPrefix="local" %> a) 在页面上, <%@ 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" /> b) 在 web.config 中,在 system.web > pages > controls, <add tagPrefix="local" namespace="Controls" assembly="App_Code" />

3) And, finally, of course, refer to it as <local:HiddenField2...> . 3) 最后,当然,将其称为<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附加参考: 在网站工程中扩展asp.net控件

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[] .要扩展 @Anders 的解决方案,使用CustomValidator方法,您可以非常轻松地获取标准HiddenField控件的值,方法是首先找到控件,对其进行强制转换,然后使用其UniqueIDPage.Request.Form[]


Example 1: Improving the Compare Validator示例 1:改进比较验证器

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.下面是CompareValidator.EvaluateIsValid()方法调用的改进版本,以添加对验证HiddenField控件的支持。 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 .请注意,此技术可以应用于任何验证器,而不是将HiddenField包装在自定义控件中,但ControlPropertiesValid方法也应该被重写以在存在HiddenField的情况下识别并返回 true。

...

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示例 2:自定义动态验证器

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 .我的DynamicRequiredFieldValidator就是一个这样的验证器,它继承自内置的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.动态验证器有两个自定义属性, ControlThatEnablesControlValueThatEnables ,用于决定是否应该打开验证器。 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.下面是确定是否应启用验证器的方法的片段,但请注意,如上所述,同样的技术可以应用于验证HiddenField而无需将其包装在自定义控件中。

...

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.作为开发人员,实施决定最终取决于您,但我的偏好是将现有验证器包装在自定义控件中,而不是将HiddenFieldsTextBoxesDropDownLists等内容包装在自定义控件中。 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;我喜欢这个解决方案的主要原因有两个:(1)包装验证器只需要几分钟而不是仅仅添加ValidationProperty ,但提供了更大的灵活性和进一步改进 .NET 验证的机会,例如,可以将FindControl调用指向一些自定义方法,在当前NamingContainer中搜索所需的控件 ID(默认),然后在未找到控件时将搜索扩展到外部PageNamingContainer的父级; (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 . (2) 恕我直言,如果有人试图改进验证,那么改进验证会更干净,相反,如果有人试图改进WebControl ,那么改进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.我完全尊重@Scotty 的解决方案,并且会第一个承认,如果这是唯一要进行的更改,那么他的解决方案将比这个解决方案多节省 5 分钟。 IMHO however, @Anders' is likely to be a better choice, in the long run.然而,恕我直言,从长远来看,@Anders' 可能是一个更好的选择。

I'd go with a CustomValidator client side我将 go 与CustomValidator客户端

<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!" />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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