使CustomValidator与ValidationSummary消息框配合工作的优雅方法

19

我以前遇到过这个问题,但从未完全解决它。我有一个带有几个验证器和 CustomValidator 的表单。

<asp:Label ID="lblMemberNum" runat="server" Text="Membership #:" CssClass="LabelMedium"  ></asp:Label>
<asp:TextBox ID="txtMemberNum" runat="server" CssClass="TextBox" ></asp:TextBox>
<asp:RequiredFieldValidator ID="rfvMemberNum" SetFocusOnError="True" runat="server"
    ControlToValidate="txtMemberNum" ErrorMessage="[ Membership # ] is required"
    CssClass="ValidationMessage" Display="Dynamic" >*</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="revMemberNum"  Display="Dynamic" runat="server" 
    ControlToValidate="txtMemberNum" CssClass="ValidationMessage" 
    ErrorMessage="[ Membership # ] can only contain letters" 
    ValidationExpression="^([a-zA-Z\d]+)$" >*</asp:RegularExpressionValidator>
<asp:CustomValidator ID="cvMemberNum" runat="server" 
    CssClass="ValidationMessage" Display="Dynamic"
    ControlToValidate="txtMemberNum" ValidateEmptyText="false"
    OnServerValidate="cvMemberNum_Validate" 
    ErrorMessage="This membership number is already registered">*</asp:CustomValidator>

<asp:ValidationSummary ID="ValidationSummary1" runat="server" 
    CssClass="ValidationMessage" 
    ShowMessageBox="True" ShowSummary="False" />

并且在服务器端:

protected void cvMemberNum_Validate(object source, ServerValidateEventArgs args)
{
    try
    {
        args.IsValid  = (!CampaignRegistration.IsMemberRegistered(args.Value));
    }
    catch
    {
        args.IsValid = false;
    }
}

我的问题是:ValidationSummary从CustomValidator中获取的消息从未显示。这个问题已经在多个地方提出过,但我没有看到令人满意的答案。

7个回答

10

尝试在所有验证器和验证摘要上使用ValidationGroup属性。

编辑:另一个可能性是服务器验证代码。

args.IsValid = (!CampaignRegistration.IsMemberRegistered(args.Value));

如果CampaignRegistration.IsMemberRegistered(args.Value)返回false,那么"!"会使它变为true,从而使其有效。我认为你应该按以下方式去掉"!":

if (CampaignRegistration.IsMemberRegistered(args.Value)) { // code when member is registered }

args.IsValid = CampaignRegistration.IsMemberRegistered(args.Value);

更新: 为了使ValidationSummary在消息框中显示您的自定义验证程序的消息,您需要拥有ClientValidationFunction代码。如果您只需要显示摘要而不需要弹出窗口,则不需要此功能。

<asp:CustomValidator ID="cvMemberNum" runat="server" 
    CssClass="ValidationMessage" Display="Dynamic"
    ControlToValidate="txtMemberNum" ValidateEmptyText="false"
    OnServerValidate="cvMemberNum_Validate"
    ClientValidationFunction = "ClientValidate"  
    ErrorMessage="This membership number is already registered">*</asp:CustomValidator>
   //JavaScript Code.
   function ClientValidate(source, args)
   {         
      args.IsValid = false; //you need to add validation logic here
   }

MORE:如果您不想进行客户端验证,可以尝试使用此技巧来显示警报。请将以下更改应用于您的CustomValidator ServerValidate方法:

protected void cvMemberNum_Validate(object source, ServerValidateEventArgs args)
{
    bool isValid = true;
    try
    {
        isValid  = (!CampaignRegistration.IsMemberRegistered(args.Value));
    }
    catch
    {
        isValid = false;
    }
    args.IsValid = isValid;

    if(!isValid)
    {
       if(!Page.IsClientScriptBlockRegistered("CustomValidation")) 
         Page.RegisterClientScriptBlock("CustomValidation", "<script>alert('This membership number is already registered');</script>"); 

    }

}

我很确定问题不在那里。不过,我会尝试一下并回报情况。 - Alfero Chingono
我在观察后更新了我的帖子。请确认。 - Jose Basilio
你所标记的代码实际上是正确的。如果用户已经注册,验证将失败。这部分是有效的。问题在于,'*'出现在文本框旁边,但ValidationSummary没有呈现消息框。 - Alfero Chingono
如果您希望验证摘要显示为消息框,则需要在CustomValidator中将EnableClientScript设置为true。您尝试过使用ShowSummary吗?看看它是否有效? - Jose Basilio
1
这是使用标准控件在消息框中显示的唯一方法。但是,您可以尝试在ServerValidate方法中注册客户端脚本,以使警报显示出来。 - Jose Basilio
显示剩余2条评论

7
ShowMessageBox选项完全是客户端的,所以只有在CustomValidator上设置了ClientValidationFunction时,它才会被评估。
您还可以通过注册一个脚本来模拟它,使其弹出一个警告,因此当您从服务器的验证返回时,它将提示错误消息。这可以在ServerValidate方法中注册(按照@Jose Basilio),或者您可以在PreRender事件期间调用以下方法以在页面上注册所有无效验证器的弹出窗口:
    /// <summary>
    /// Registers a script to display error messages from server-side validation as the specified <see cref="UserControl"/> or <see cref="Page"/> loads from a postback.
    /// </summary>
    /// <remarks>
    /// Must be called in the PreRender if used to validate against the Text property of DNNTextEditor controls, otherwise Text will not be populated.
    /// Must set the ErrorMessage manually if using a resourcekey, otherwise the resourcekey will not have overridden the ErrorMessage property.
    /// </remarks>
    /// <param name="ctrl">The <see cref="UserControl"/> or <see cref="Page"/> which is being posted back.</param>
    /// <param name="validationGroup">The validation group against which to validate.</param>
    public static void RegisterServerValidationMessageScript(TemplateControl ctrl, string validationGroup)
    {
        if (ctrl != null && ctrl.Page.IsPostBack)
        {
            ctrl.Page.Validate(validationGroup);
            if (!ctrl.Page.IsValid)
            {
                StringBuilder errorMessage = new StringBuilder("<script language='javascript'>alert('");
                for (int i = 0; i < ctrl.Page.Validators.Count; i++)
                {
                    IValidator validator = ctrl.Page.Validators[i];
                    if (!validator.IsValid)
                    {
                        errorMessage.Append("- " + validator.ErrorMessage);
                        if (i < ctrl.Page.Validators.Count - 1)
                        {
                            errorMessage.Append(@"\r\n");
                        }
                    }
                }

                errorMessage.Append("');</script>");
                ctrl.Page.ClientScript.RegisterStartupScript(typeof(IValidator), "validationAlert", errorMessage.ToString(), false);
            }
        }
    }

目前唯一的问题是,我不被允许渲染自定义JS。 - Alfero Chingono

5

我最近遇到了同样的问题。当ServerValidate声明验证失败时,ValidationSummary未显示CustomValidator中的ErrorMessage。由于默认情况下(根据我的小型反向工程),验证摘要在回发时以客户端方式呈现,因此我只需添加一个脚本,在文档加载/异步回发完成时检查所有验证器并触发验证摘要创建以获取失败的验证组:

$(document).ready(function () {
    var displayAlert = function () {
        if (typeof Page_Validators == 'undefined') return;

        var groups = [];
        for (i = 0; i < Page_Validators.length; i++)
            if (!Page_Validators[i].isvalid) {
                if (!groups[Page_Validators[i].validationGroup]) {
                    ValidationSummaryOnSubmit(Page_Validators[i].validationGroup);
                    groups[Page_Validators[i].validationGroup] = true;
                }
            }
    };

    displayAlert();

    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(
                    function () {
                        displayAlert();
                    });
}
);

在我的场景中,我有嵌套的用户控件,包含验证器、更新面板和父页面上的验证摘要。

这里有更多细节。


1
你应该在每个验证器中编写一个属性:ValidationGroup="ValidationSummary1"。此外,检查一下你的页面是否有这个属性。
AutoEventWireup="true"

CustomValidator实际上验证并执行服务器端代码。当无效时,它会在文本框旁边显示其文本(“*”)。然而,ValidationSummary显示其他消息,但不是来自CustomValidator。 - Alfero Chingono
只需尝试这两个指令,然后告诉我。因为我完全有相同的情况,并且来自自定义验证器的消息出现在验证总结中。 - Iralda Mitro
谢谢您的回复,DaDa。也许我应该澄清一下,如果我设置ShowSummary="true",ValidationSummary会显示来自CustomValidator的错误。问题是当我想显示一个消息框时。 - Alfero Chingono

1
bduke的RegisterServerValidationMessageScript在“伪造”,但实际上不是。它真正地解决了这个问题。每个Utility命名空间都需要在某个位置拥有此函数。

1

我已经找到了一个解决办法,用于当 JavaScript 被禁用时,ValidationSummary 不显示 CustomValidatorerrorMessage 属性。由于注入脚本或警报不起作用,这是必需的。

添加一个新的验证控件,我们称之为 CustomValidatorProxy,将其 ControlToValidate 属性设置为表单上的任何控件,并将 EnableClientScript=false

ServerValidate 事件处理程序中执行自定义验证,如果验证失败,则将 CustomValidatorCustomValidatorProxyIsValid 属性设置为 false,并同样设置两个 ErrorMessage 属性。

如果在 ServerValidate 中通过了验证,请确保将 CustomValidatorProxy 的 IsValid 属性设置为 true。

如果在页面的ValidatorCollection中,CustomValidatorProxyCustomValidator之前,则ServerValidate处理程序将重写IsValid属性值,该值将由CustomValidatorProxy返回并验证ControlToValidate值,并且你的CustomValidator中的ErrorMessage将在ValidationSummary中显示。


0
这对我有用:
<asp:CustomValidator runat="server" ID="cv" 
ClientValidationFunction="ValidateFunction"
ErrorMessage="Default error
message">*</asp:CustomValidator>

<script type="text/javascript">
function ValidateFunction(sender, args) 
{

var msg ='';
var formValid = true;

[various checks setting msg and formValid]

if (msg.length > 0) { sender.errormessage = msg; }
args.IsValid = formValid;

}
</script>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接