我有 3 个组合框显示 MVC 中的出生年月日。我想计算年龄并禁止动态小于 18 岁的人注册。虽然是 JS。
类似于此图像中显示的内容:
这是通过使用 DataAnnotations 和 EditorFor 完成的。实际的源代码类似于以下内容。我应该如何修改以同时验证 3 个控件?
[Required(ErrorMessageResourceType = typeof (Resources),
ErrorMessageResourceName = "RequiredField")]
[Range(1, 31)]
[LocalizedDisplayName(typeof (RA.Resources), "RegistrationDayOfBirth")]
public int BirthDay { get; set; }
[Required(ErrorMessageResourceType = typeof (Resources),
ErrorMessageResourceName = "RequiredField")]
[Range(1, 12)]
[LocalizedDisplayName(typeof (RA.Resources), "RegistrationMonthOfBirth")]
public int BirthMonth { get; set; }
[Required(ErrorMessageResourceType = typeof (Resources),
ErrorMessageResourceName = "RequiredField")]
[Range(1800, int.MaxValue, ErrorMessageResourceType = typeof (Resources),
ErrorMessageResourceName = "MoreThanFieldRequired")]
[LocalizedDisplayName(typeof (RA.Resources), "RegistrationYearOfBirth")]
public int BirthYear { get; set; }
[LocalizedDisplayName(typeof (RA.Resources), "RegistrationDateOfBirth")]
public DateTime DateOfBirth { get; set; }
最佳答案
如果您想坚持使用 3 字段方法并进行动态验证(即,如果我明天 18 岁生日,今天拒绝我访问,但明天让我进入),您将需要发挥创意。
然后您需要创建一个自定义验证器和一些自定义属性。
如何进行此操作取决于您要完成的工作量,以及您要在何处应用验证逻辑。
仅服务器端验证
最简单的选择是在类本身上定义它 - 但是这将限制您只能进行服务器端验证。
创建一个在类级别应用的自定义属性,期望类上有三个字段(我添加了一个接口(interface)来简化这个并且不需要反射)并根据需要验证它:
// Interface to define individual fields:
public interface IHasIndividualDateOfBirth
{
int BirthDay { get; set; }
int BirthMonth { get; set; }
int BirthYear { get; set; }
}
// Note new class level attribute, and interface declaration:
[MinAge(AgeInYears = 18)]
public class Birthday: IHasIndividualDateOfBirth
{
[Required]
[Range(1, 31)]
public int BirthDay { get; set; }
[Required]
[Range(1, 12)]
public int BirthMonth { get; set; }
[Required]
[Range(1800, 2200)]
public int BirthYear { get; set; }
public DateTime BirthDate { get; set; }
}
// Declare a new ValidationAttribute that can be used at the class level:
[AttributeUsage(AttributeTargets.Class)]
public class MinAgeAttribute : ValidationAttribute
{
public int AgeInYears { get; set; }
// Implement IsValid method:
protected override ValidationResult IsValid(object value,
ValidationContext validationContext)
{
// Retrieve the object that was passed in as our DateOfBirth type
var objectWithDob = validationContext.ObjectInstance
as IHasIndividualDateOfBirth;
if (null != objectWithDob)
{
// TODO: Handle invalid dates from the front-end (30 Feb for example)
DateTime dateOfBirth = new DateTime(objectWithDob.BirthYear,
objectWithDob.BirthMonth,
objectWithDob.BirthDay);
// Check that the age is more than the minimum requested
if (DateTime.Now >= dateOfBirth.AddYears(AgeInYears))
{
return ValidationResult.Success;
}
return new ValidationResult("You are not yet 18 years old");
}
return new ValidationResult("Class doesn't implement IHasIndividualBirthday");
}
}
虽然实现 IValidatableObject
可能看起来更简单,但它不像使用属性那样灵活,而且(像上面基于类的验证)不提供执行客户端的方法验证。
其他选项是创建一个依赖于许多其他字段的验证器(在这种情况下,您可能需要使用反射来查找其他字段,并确定哪些字段去哪里)并且您需要确保您只触发一次验证器(而不是在每个字段上),或者为 DateTime 属性编写一个自定义验证器和编辑器,而不是呈现一个您可以将日历控件放到其中的单个字段,创建三个单独的字段之后。
客户端和服务器端验证
要使客户端验证正常工作,您需要在属性级别执行此操作,这将需要您做一些额外的工作 - 例如,您可以使用模型上的 DateTime 字段作为隐藏字段当用户填写各个字段时通过 JS 填充,然后对其进行验证。
然后您的属性将需要实现 IClientValidatable
,这将使您能够连接到客户端验证选项,并在元素上呈现一些元数据以公开年龄要求:
[AttributeUsage(AttributeTargets.Property)]
public class MinAgeAttribute : ValidationAttribute, IClientValidatable
{
public int AgeInYears { get; set; }
protected override ValidationResult IsValid(object value,
ValidationContext validationContext)
{
// [Similar to before]
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(
ModelMetadata metadata,
ControllerContext context)
{
return new[]
{
new ModelClientValidationMinAgeRule(ErrorMessage, AgeInYears)
};
}
}
public class ModelClientValidationMinAgeRule : ModelClientValidationRule
{
public ModelClientValidationMinAgeRule(string errorMessage, int ageInYears)
{
ErrorMessage = errorMessage;
// Validation Type and Parameters must be lowercase
ValidationType = "minage";
ValidationParameters.Add("ageinyears", ageInYears);
}
}
然后对于客户端,您需要将一些自定义验证器注册到 jQuery.Validate 或类似工具中(我推荐您自己的 JS 文件包含在 jqueryval
包中):
$(function ($) {
$.validator.addMethod("minage", function(value, element, params) {
if ($(element).val() != '') {
var ageInYears = params;
// take date from BirthDate element and compare with ageInYears.
return false;
}
});
$.validator.unobtrusive.adapters.addSingleVal("minage", "ageinyears");
}(jQuery));
关于c# - ASP.NET MVC : validating age > 18 having 3 combo box,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26342936/