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");
}
}
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With