扩展ASP.NET验证器

时间:2010-08-01 06:53:04

标签: asp.net validation

我想扩展as​​p.net验证器,以便我可以使一个验证器依赖于另一个验证器。我的情况是我们必须在文本框中验证日期。通常我会使用RequiredFieldValidator的组合(以确保提供日期),CompareValidator(以确保日期是日期),最后使用RangeValidator(以确保日期在所需的限制范围内)。

问题在于验证器不依赖于彼此,因此当我们希望他们真正想要看到的是最相关的消息时,用户可能会立即看到每个验证器的所有三个消息,即如果他们在日期文本框中输入“abc”,则向他们显示日期不在有效范围内的消息是不合适的(尽管从技术上讲我认为这是真的)。​​

目前为了提供这种功能,我们使用CustomValidator并将所有三个验证放在服务器验证事件处理程序中,并根据验证失败以编程方式更改错误消息。

我想在这个应用程序中进行相当多的标准化,我想如果我可以使验证器相互依赖,这将解决问题,并允许我们使用客户端验证而不是必须进行回发,尤其是处理自定义验证。

这个想法是,如果一个验证器依赖于另一个验证器,如果“master”有效,那么depended将执行其正常验证(EvaluateIsValid())否则如果主验证器无效,那么其他依赖验证器将是有效的

我通过继承框架中已经提供的各种验证器控件来提出以下解决方案。

public class RequiredFieldDependentValidator : RequiredFieldValidator
{
    [Description("The validation control to depend on for determining if validation should occur")]
    public string ValidationControlToDependOn
    {
        get
        {
            object obj = ViewState["ValidationControlToDependOn"];
            if (obj != null) return (string) obj;
            return null;
        }
        set
        {
            Control control = FindControl(value);
            if (control is IValidator)
                ViewState["ValidationControlToDependOn"] = value;
            else
                throw new HttpException("ValidationControlToDependOn is not a validation control");
        }
    }

    protected override bool EvaluateIsValid()
    {
        IValidator validationControlToDependOn = FindControl(ValidationControlToDependOn) as IValidator;

        if(validationControlToDependOn != null)
        {
            return !validationControlToDependOn.IsValid || base.EvaluateIsValid();
        }

        return base.EvaluateIsValid();
    }

目前我刚刚为RequiredFieldValidator编写了代码,理想情况下我想为所有验证器提供此功能,但是如果不将上述代码复制到每个类型的验证器的类似类中,我就看不到这样做的方法我想提供这个功能,因此如果有任何问题,我将不得不返回并在每个验证器类型上单独更改此代码。

有没有一种方法可以“集中”这些代码,并且可以在验证器中轻松使用它,而无需从头开始编写整个验证器,这样我就可以更改它们继承的类。

干杯,

4 个答案:

答案 0 :(得分:1)

您可以覆盖页面基础中的Validate方法。要在页面中添加验证依赖项信息,您可以实现一个未呈现的控件:

<my:ValidationDependency TargetControl="RegExp1" Dependency="Required1" />

答案 1 :(得分:0)

您可以拥有类型为List的ValidationControlToDependOn属性,并将验证器添加到列表中。因此,我们可以假设稍后添加的验证器取决于之前添加的验证器。

所以你的protected override bool EvaluateIsValid()

会有所改变

foreach(IValidator validator in ValidationControlToDependOn)
{
return !validator.IsValid;

}

答案 2 :(得分:0)

我正在研究控制扩展器,这看起来很有希望,但我找不到很多做任何事情的例子,除了AJAX的东西。

答案 3 :(得分:0)

您可能希望查看WebControlAdapter。

基本上允许你覆盖web控件的某些方法(如果需要,可以有条件地使用某些浏览器,但这里可以适用于所有浏览器。)

在您的情况下,您可能希望覆盖EvaluateIsValid方法并检查控件是否依赖于“父”验证器。

例如,我们最近创建的TextBox适配器用于向控件呈现“maxlength”属性。

Public Class TextBoxAdapter
        Inherits WebControlAdapter

        Private ReadOnly Property TextBoxControl() As TextBox
            Get
                Return DirectCast(MyBase.Control, TextBox)
            End Get
        End Property

        Protected Overrides Sub RenderBeginTag(ByVal writer As System.Web.UI.HtmlTextWriter)
            If TextBoxControl.TextMode = TextBoxMode.MultiLine AndAlso TextBoxControl.MaxLength > 0 Then
                writer.AddAttribute("maxlength", TextBoxControl.MaxLength.ToString)
            End If

            MyBase.RenderBeginTag(writer)
        End Sub
    End Class

要使用它,只需在App_Browsers目录中创建一个.browser文件并在那里设置适配器:

<browsers>
    <browser refID="Default">
        <controlAdapters>
            <adapter controlType="System.Web.UI.WebControls.TextBox"
               adapterType="TextBoxAdapter" />
        </controlAdapters>
    </browser>
</browsers>

在您的情况下仍然存在的唯一复杂因素是如何存储依赖验证器,以便EvaluateIsValid有权访问此目录。您可能会考虑像Onof建议的非渲染控件或Viewstate / Cookie /其他存储机制。