asp:RequiredFieldValidator不验证隐藏字段

问题描述 投票:22回答:6

ASP.NET验证器似乎不验证隐藏字段。我得到这样的消息:

无法验证由“hiddenFieldValidator”的ControlToValidate属性引用的控件“hiddenField”。

我的页面中有一个<asp:HiddenField>,它在客户端充满了一些价值。我需要在服务器上出现一次,所以我添加了一个RequiredFieldValidator

它不起作用!

在我看来,作为一种解决方法,我可以:

1.使用自定义验证器而不将其绑定到隐藏字段,只需在OnServerValidate上调用方法;

2.使用带有CSS样式的<asp:TextBox>display:none,它应该可以工作。

但我想确保我在这里没有遗漏一些东西。是否可以以与其他文本字段相同的方式验证隐藏字段?哦,也许是第三个更优雅的选择?

TIA!

c# asp.net validation webforms controls
6个回答
5
投票

正如您所说的异常消息所示,似乎HiddenField控件无法直接通过标准验证控件进行定位。我会选择CustomValidator解决方法。


36
投票

@彼得的回答让我思考,ControlPropertiesValid实际检查了什么?

看看MSDN topic,它寻找ValidationPropertyAttribute等等。嗯,所以如果我们只是从HiddenField派生并用ValidationPropertyAttribute设置为Value(为了我的目的)装饰新类,那么“一切正常”。确实如此。

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

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

用法 - 确保注册包含控件的程序集:

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

在您的Page / UserControl内容中:

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

所有验证器都可以使用它。额外的好处是,如果你(像我一样)使用自定义验证功能,你可以轻松评估HiddenField2.Value,因为它包含在args.Value字段中(在服务器端,这是ServerValidateEventArgs)。


5
投票

这是我提出的解决方法,因为遗憾的是我找不到任何可靠的方法来使用RequiredFieldValidator或开箱即用的CustomValidator进行验证。如果将ControlToValidate属性保留为空,则会对您大喊大叫。您所要做的就是创建一个自定义控件,如下所示:

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

通过覆盖属性有效检查以使其始终返回true,它不再关心您正在使用HiddenField,它将从中提取值并验证没有问题。


4
投票

这是Scotty.NET对解决方案的回应。我只是没有足够的声誉来回复。

给Scotty.NET +1!

对于我们这些对.NET和编译不够了解的人来说,这可能有助于简化他人对其他人的回答。

我想在使用Visual Web Developer 2010 Express的网站中使用它:

1)我将派生的HiddenField2保存在/ App_Code中作为HiddenField2.cs,只需更改一次 - > namespace Controls

2)然后,注册控件:

a)在页面上,<%@ Register Assembly="App_Code" Namespace="Controls" TagPrefix="local" %>

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

3)最后,当然,将其称为<local:HiddenField2 ...>

它确实使得时髦的代码着色。可能相当容易改进命名空间来处理它。在我当地的环境中为我精彩地工作;我不知道它在实时服务器上不会出现问题。

补充参考:extending asp.net control in the website project


4
投票

为了扩展@Anders的解决方案,使用CustomValidator方法,您可以通过首先找到控件,投射它,然后使用其HiddenFieldUniqueID中查找其值来轻松获取标准Page.Request.Form[]控件的值。

示例1:改进比较验证器

此示例可能更适合您的实现。以下是CompareValidator.EvaluateIsValid()方法调用的改进版本,以便添加对验证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);
}

...    

示例2:自定义动态验证器

这个例子比第一个例子复杂一点。我经常使用根据页面上另一个控件的值启用或禁用的自定义动态验证器(例如,如果选中该框,则需要此文本框;否则无需验证)。一个这样的验证器是我的DynamicRequiredFieldValidator,它继承自内置的RequiredFieldValidator。动态验证器有两个自定义属性ControlThatEnablesControlValueThatEnables,用于决定是否应该打开验证器。下面是该方法的一个片段,用于确定是否应启用验证器,但请注意,如上所述,这种相同的技术可用于验证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;
    }
}

...

最后的想法

作为开发人员,实现决策最终取决于您,但我的首选是将现有验证器包装在自定义控件中,而不是在自定义控件中包装HiddenFieldsTextBoxesDropDownLists等。我有两个主要的理由来选择这个解决方案:(1)包装验证器只需要几分钟而不仅仅是添加ValidationProperty,但是提供了更大的灵活性和进一步改进.NET验证的机会,例如:可以指出FindControl调用一些自定义方法,在当前的NamingContainer(默认)中搜索所需的控件ID,然后将搜索扩展到外部PageNamingContainer的父级(如果未找到控件); (2)恕我直言,如果一个人试图改进验证,改进验证是更清洁,相反,如果一个人试图改善WebControl,改善WebControl更清洁。

我完全尊重@ Scotty的解决方案,并且会首先承认,如果这是唯一的改变,那么他的解决方案将比你节省5分钟。恕我直言,从长远来看,@安德斯可能是一个更好的选择。


0
投票

我会去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!" />
© www.soinside.com 2019 - 2024. All rights reserved.