如何定制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属性/字段验证消息的主要内容,如果未能解决你的问题,请参考以下文章