如何使用DataAnnotation进行自定义验证并从config appsettings.json获取值?

时间:2018-10-15 13:03:30

标签: c# asp.net-core asp.net-core-mvc

我正在对ASP.NET Core MVC(2.1)中的输入字段进行自定义验证。 我想添加一个简单的Captcha字段,要求用户输入一些可以在appsettings.json文件中轻松重新配置的数字。我知道那里有很多库验证码,但这不是我想要的这种特殊情况。

我无法从appsettings.json获取值。下面的代码可以完美地编译,但是我不知道如何从CaptchaCustomAttribute类的appsettings.json文件中获取值。

这是我的代码:

// 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");
    }
}

1 个答案:

答案 0 :(得分:1)

您在问题中注释掉的代码非常接近工作,除了一个小细节。使用IServiceCollection.Configure<T>时,您将(除其他事项外)将IOptions<T>的注册添加到DI容器中,而不是添加T本身的注册。这意味着您需要在IOptions<GeneralConfiguration>实现中要求一个ValidationAttribute,如下所示:

var serviceOptions = (IOptions<GeneralConfiguration>)
    validationContext.GetService(typeof(IOptions<GeneralConfiguration>));
var service = serviceOptions.Value;