我有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岁生日是明天,请拒绝我今天访问,但是明天让我访问),您将需要发挥创造力。
You'll then need to create a custom validator, and some custom attributes to go with it.
How you go about this depends on the amount of work you want to do, and where you want to apply the validation logic.
The simplest option is to define this on the class itself - however this will limit you to server-side validation only.
Create a custom attribute that is applied at the class level that expects there to be three fields on the class (I've added an interface to make this simpler and not require reflection) and validate this as required:
// 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");
}
}
While implementing IValidatableObject
may seem simpler still, it isn't as flexible as using an attribute and also (like the class-based validation above) doesn't provide a way to perform client-side validation.
Other options would be to create a validator that depends on a number of other fields (in which case you would probably need to use reflection to look for other fields, and work out which ones go where) and you'd need to ensure you're only firing the validator once (rather than on every field), or to write a custom validator and editor for the DateTime property that instead of rendering a single field that you could drop a calendar control onto creates the three separate fields you're after.
To get client-side validation working, you'll need to do this at the property level, which will require you to do some additional work - you could for example use the DateTime field you have on the model as a hidden field that is populated via JS as the user fills in the individual fields and then validate that.
然后,您的属性需要实现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或类似版本中(我建议您在jqueryval
捆绑包中包含您自己的JS文件):
$(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));
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句