Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do custom validation with DataAnnotation and get value from config appsettings.json?

I am doing custom validation on a input field in ASP.NET Core MVC (2.1). I would like to add a simple Captcha field asking user to enter some numbers which can be easily reconfigured in appsettings.json file. I know there are plenty of libraries out there doing Captcha's but this is not what I want for this particular case.

I having trouble getting the value from the appsettings.json. The below code compiles perfectly but I don't know how to get the value from appsettings.json file in the CaptchaCustomAttribute class.

Here is my code:

// appsettings.json
{ 
  "GeneralConfiguration": {
    "Captcha":  "123456"
    }
}

// GeneralConfiguration.cs
public class GeneralConfiguration
{
    public string Captcha { get; set; }
}

// startup.cs / dependency injection
public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<GeneralConfiguration>(Configuration.GetSection("GeneralConfiguration"));
 }

// form model
public class ContactFormModel {
  ... simplified 

  [Display(Name = "Captcha")]
  [Required(ErrorMessage = "Required")]
  [CaptchaCustom]
  public string Captcha { get; set; }

}

// CaptchaCustomAttribute.cs
public sealed class CaptchaCustomAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null) return new ValidationResult("value cannot be null");
        if (value.GetType() != typeof(string)) throw new InvalidOperationException("can only be used on string properties.");

        // get value of Captcha here. How?  

        // this will fail for obvious reasons
        //var service = (GeneralConfiguration)validationContext
        //            .GetService(typeof(GeneralConfiguration));

        //if ((string)value == service.Captcha)
        //{
        //    return ValidationResult.Success;
        //}
        return new ValidationResult("unspecified error");
    }
}
like image 941
Sha Avatar asked Oct 17 '22 12:10

Sha


1 Answers

The code you've commented-out in your question is very close to working, except for one small detail. When you use IServiceCollection.Configure<T>, you are adding (amongst other things) a registration for IOptions<T> to the DI container, rather than a registration for T itself. This means you need to ask for an IOptions<GeneralConfiguration> in your ValidationAttribute implementation, like so:

var serviceOptions = (IOptions<GeneralConfiguration>)
    validationContext.GetService(typeof(IOptions<GeneralConfiguration>));
var service = serviceOptions.Value;
like image 152
Kirk Larkin Avatar answered Oct 20 '22 23:10

Kirk Larkin