Asp.NET MVC:验证年龄> 18(具有3个组合框)

上一个

我有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.

Server-side only validation

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.

Client- and server-side validation

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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在 ASP.NET Core MVC 中使用 jquery 验证进行日期和年龄验证

ASP.NET MVC3验证类型名称错误

具有表单身份验证的ASP.NET MVC和具有基本身份验证的WebApi

具有MVC 5的ASP.NET Identity版本3?

ASP.NET MVC中具有jQuery非干扰性验证的页面上的多种表单

仅当另一个文本框具有值时才验证下拉列表 - ASP.NET

带有JQuery的ASP.NET MVC,JQuery验证和引导程序,验证不便之处

无法修复 ASP.NET MVC 验证

ASP.NET MVC:输出验证

ASP.NET MVC删除模型验证

ASP.NET MVC 5表单验证

带有ELMAH.MVC的ASP.NET MVC站点-Windows身份验证

ASP.NET MVC级联组合框

ASP.NET MVC 组合框值加载

Javascript电子邮件验证错误(在ASP.Net中有效,而在ASP.Net MVC中无效)

asp.net和asp.net MVC之间的表单身份验证有区别吗?

ASP.NET MVC - 两个应用程序之间的相同身份验证

在两个日期之间进行比较的ASP.NET MVC jQuery非侵入式验证

在 ASP.NET Core MVC 中一次验证两个属性

如何避免在没有验证电子邮件的情况下登录 asp.net mvc

ASP.NET 5 MVC 6中没有实体框架的身份验证和授权

如何抑制ASP.NET MVC远程验证,直到在表单上提供所有字段?

ASP.NET Core MVC 中的 cookie 身份验证有问题

带有 ASP.NET Core MVC 控制器的 Blazor 服务器,验证问题

ASP.NET MVC3中的客户端验证

jQuery验证错误ASP.NET MVC 3-jquery.validate.min.js

在MVC 5中具有ASP.NET Identity的Autofac无法验证OWIN管道中的安全标记

具有asp.net核心的Windows身份验证

是否可以在一个ASP.NET MVC应用程序中同时具有Azure AD和个人帐户身份验证?