如何定制Numeric属性/字段验证消息

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何定制Numeric属性/字段验证消息相关的知识,希望对你有一定的参考价值。

参考技术A   一、针对Numeric属性/字段默认验证消息
  我们先来通过一个简单的例子来验证这个问题,为此我们定义了如下一个表示员工信息的Employee类型,其中代表年龄的Age属性类型为整型。

  1: public class Employee
  2:
  3: [Display(Name = "姓名")]
  4: public string Name get; set;
  5:
  6: [Display(Name = "性别")]
  7: public string Gender get; set;
  8:
  9: [Display(Name = "年龄")]
  10: public int Age get; set;
  11:
  我们创建一个Model类型为Employee的View对某个元员工的信息进行修改。如下图所示,当我们输入一个非数字字符串作为Age字段的时候,验证错误信息显示为“The field 年龄 must be a number”,值得一提的是:当前线程的CurrentUICulture为zh-CN。

  image

  二、默认的验证消息来源于何处?
  针对数字类型字段进行验证的是一个名称为NumericModelValidator的ModelValidator,不过这是个定义在System.Web.Mvc程序集中俄内部类型。如果采用Reflector查看其定义,可以发现用于返回错误消息的方法是一个名为MakeErrorString的静态方法。如下面的代码所示,作为错误消息的字符串来源于内嵌于程序集中的资源文件。

  1: internal sealed class NumericModelValidator : ModelValidator
  2:
  3: //其他成员
  4: private static string MakeErrorString(string displayName)
  5:
  6: return string.Format(CultureInfo.CurrentCulture, MvcResources.ClientDataTypeModelValidatorProvider_FieldMustBeNumeric, new object[] displayName );
  7:
  8:
  NumericModelValidator最终是通过ClientDataTypeModelValidatorProvider这个一个ModelValidatorProvider提供的。

  三、通过自定义ModelValidatorProvider替换NumericModelValidator
  如果我们想改变内部类型NumericModelValidator的错误消息,可以通过将ClientDataTypeModelValidatorProvider提供的NumericModelValidator替换成另一个ModelValidator。在这里我们替换的是一个DataAnnotationsModelValidator,而它基于的ValidationAttribute是我们自定义的NumericAttribute。

  如下面的代码片断所示,内部类型NumericAttribute是ValidationAttribute的子类,并且实现了IClientValidatable接口。在这里我么只考虑客户端验证,所以重写的IsValid方法直接返回True,而GetClientValidationRules方法则返回一个包含一个验证类型为“number”的ModelClientValidationRule对象的集合。我们使用FormatErrorMessage方法格式化后的字符串作为ModelClientValidationRule的ErrorMessage属性。

  1: internal class NumericAttribute : ValidationAttribute, IClientValidatable
  2:
  3: public override bool IsValid(object value)
  4:
  5: return true;
  6:
  7: public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
  8:
  9: yield return new ModelClientValidationRule ValidationType = "number", ErrorMessage = this.FormatErrorMessage(metadata.DisplayName);
  10:
  11:
  现在我们需要做的就是通过一个自定义ModelValidatorProvider将ClientDataTypeModelValidatorProvider提供的NumericModelValidator替换成基于NumericAttribute的DataAnnotationsModelValidator,所以我们定义了一个直接继承自ClientDataTypeModelValidatorProvider的FilterableClientDataTypeModelValidatorProvider。如下面的代码所示,在重写的GetValidators方法中我们完成了针对NumericModelValidator的替换。对于被创建的NumericAttribute来说,我们指定的错误消息也定义在Resource文件中(为了提供多语言的支持),而基于zh的内容为“0必须是一个数字!”。

  1: public class FilterableClientDataTypeModelValidatorProvider : ClientDataTypeModelValidatorProvider
  2:
  3: public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
  4:
  5: var allValidators = base.GetValidators(metadata, context);
  6: var validators = new List<ModelValidator>();
  7: foreach (var v in allValidators)
  8:
  9: if (v.GetType().Name != "NumericModelValidator")
  10:
  11: validators.Add(v);
  12:
  13: else
  14:
  15: NumericAttribute attribute = new NumericAttribute ErrorMessage = Resources.FieldMustBeNumeric;
  16: DataAnnotationsModelValidator validator = new DataAnnotationsModelValidator(metadata, context, attribute);
  17: validators.Add(validator);
  18:
  19:
  20: return validators;
  21:
  22:

  四、注册自定义ModelValidatorProvider
  现在我们只需要通过ModelValidatorProvider的注册让我们自定义的FilterableClientDataTypeModelValidatorProvider替换默认的ClientDataTypeModelValidatorProvider。在Global.asax中,针对FilterableClientDataTypeModelValidatorProvider的注册可以通过如下的代码来完成。

  1: public class MvcApplication : System.Web.HttpApplication
  2:
  3: //其他成员
  4: protected void Application_Start()
  5:
  6: //其他操作
  7: var clientDataTypeValidator = ModelValidatorProviders.Providers.OfType<ClientDataTypeModelValidatorProvider>().FirstOrDefault();
  8: if (null != clientDataTypeValidator)
  9:
  10: ModelValidatorProviders.Providers.Remove(clientDataTypeValidator);
  11:
  12: ModelValidatorProviders.Providers.Add(new FilterableClientDataTypeModelValidatorProvider());
  13:
  14:

在 Flutter 小部件测试中,如何验证字段验证错误消息?

【中文标题】在 Flutter 小部件测试中,如何验证字段验证错误消息?【英文标题】:In a Flutter widget test, how can I verify a field validation error message? 【发布时间】:2020-02-13 14:10:21 【问题描述】:

我正在为 Flutter 表单编写一个小部件测试,并想验证在表单提交后,验证是否失败,并且其中一个字段的 errorText 显示并符合预期。

该字段的代码如下所示:

Form(key: _formKey, ...
  TextFormField(validator: validateEmail, ...)

对于测试断言,我尝试过类似

expect(find.text('Please fill in your email.'), findsOneWidget);

没有成功。希望有人能指出我正确的方向。

【问题讨论】:

【参考方案1】:

我重新创建了您的案例,并且能够验证内联错误消息。这个想法是在我们可以测试断言之前添加 1 秒的延迟。这是我所做的:

main.dart 代码显示textformfield 并在点击Send 按钮时验证电子邮件:

TextFormField(
            decoration: new InputDecoration(hintText: 'Email ID'),
            keyboardType: TextInputType.emailAddress,
            maxLength: 32,
            validator: validateEmail,
            onSaved: (String val) 
              email = val;
            ),

validateEmail方法sn-p:

if (value.length == 0) 
      return "Email is Required";
     else if(!regExp.hasMatch(value))
      return "Invalid Email";
    else 
      return null;
    

小部件测试以验证电子邮件字段的内联错误消息:

void main() 
  testWidgets('validate email inline error message',
          (WidgetTester tester) async 

        await tester.pumpWidget(MyApp());

        final buttonFinder = find.text('Send');
        final emailErrorFinder = find.text('Email is Required');

        await tester.tap(buttonFinder);
        print('button tapped');
        await tester.pump(const Duration(milliseconds: 100)); // add delay
            expect(emailErrorFinder, findsOneWidget);
        print('validated email inline error');
      );

测试结果:

希望这能回答你的问题。

【讨论】:

感谢您的观看,不幸的是,这对我来说并没有起到作用。但是,我发现如果在我按下按钮之前,我做了一个tester.pumpAndSettle(),它就开始通过了。有点头疼! 我遇到了这个问题,无法弄清楚。我想知道它是如何为你们所有人工作的,而不是在我的设置上。希望不要手动测试,如果有人有很棒的想法。我用于提升按钮的点击是否不会以某种方式触发验证方法? @MattR 这告诉测试小部件隐含所有更改并运行所有动画,例如验证错误。

以上是关于如何定制Numeric属性/字段验证消息的主要内容,如果未能解决你的问题,请参考以下文章

如何将字段名称传递给属性文件中的全局消息

如何检查数字输入是不是为空?

在用户将数据输入字段之前如何防止验证?

使用 is_numeric 进行表单验证

如何在构建消息之前在 protobuf 中设置重复字段?

如何在 FieldArray 中包含不同值的数组的 yup 验证中添加错误消息?