How to validate an input against a changing validation requirements
Introduction
Data annotation is a server side mechanism that is used to validate a certain model attribute value in MVC.It binds a model attribute to a certain validation attribute type .Common validation attribute types include
- Required
- Range
- DataType
- Regular expression
- ....
Regular expression data annotation is used to validate a model attribute value against a certain pattern,as example below
The following data annotation checks if a model attribute value qualifies to be a valid e-mail address
[RegularExpression(@"^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$", ErrorMessage = "Email is not valid.")]The model attributes are bound to the proper data annotation while creating the model
<>What if the pattern is subject to change as per user requirements
for example user can control the complexity degree of user passwords
public partial class PasswordComplexityRuleDataModel { public int Id { get; set; } public bool MustContainLettersNumbers { get; set; } public bool MustContainSpecialCharacters { get; set; } public bool MustContainUpperLower { get; set; } public short MinLength { get; set; } }
Solution 1
call a certain validation function on each action marked as (post) Example- model
public partial class UserDataModel { /**/ public string passwordinvalid { get; set; } } ..
- Controller
public IActionResult Save(UserDataModel user) { //if(PasswrodRequirementAreMet(user.Password)) //{ //ModelState.AddModelError("passwordinvalid", ""); // || // add a span bound to this property in view} if (ModelState.IsValid) { _userServiceInterface.SaveUser(user); return RedirectToAction(nameof(Index)); } return View(user); } ..
This solution has a drawback of calling it on every action of type (post)
Solution 2
- Create a custom validation attribute to take care of validating the input
// class CustomPassWordValidation:ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { PasswordValid = CheckPasswordAgainstPasswordSettings(value.ToString()); if (PasswordValid != "password valid") { ErrorMessage = PasswordValid; return new ValidationResult(ErrorMessage); } return ValidationResult.Success; } string CheckPasswordAgainstPasswordSettings(string password) { /**/ return "password valid"; } } ...
- In the data model containing your attribute,bind the attribute to the attribute validator created above
public class UserViewModel { [CustomValidationAttribute.CustomPassWordValidation(ErrorMessage ="travesh")] public string Password { get; set; } ..
}
- If your coding standards follows the dependency injection supporting nature of asp.net core mvc,the function checking password validity may be calling a function in another interface
- you can call the interface instance using the following syntax
// class CustomPassWordValidation:ValidationAttribute { // an object type (service interface type ) protected IPasswordComplexityRuleService _passwordComplexityRuleService protected override ValidationResult IsValid(object value, ValidationContext validationContext) { //call the interface instance _passwordComplexityRuleService =(IPasswordComplexityRuleService) validationContext.GetService(typeof(IPasswordComplexityRuleService)); PasswordValid = CheckPasswordAgainstPasswordSettings(value.ToString()); if (PasswordValid != "password valid") { ErrorMessage = PasswordValid; return new ValidationResult(ErrorMessage); } return ValidationResult.Success; } string CheckPasswordAgainstPasswordSettings(string password) { /*interface instance is used here*/ return "password valid"; } } ...
Comments
Post a Comment