havij
havij

Reputation: 1170

Model validation for configuration objects in ASP.NET Core

In .NET Core, if my appsettings file looks like

{
  "Section": {
    "Field": "value"
  }
}

I can create a class like

public class Section
{
    public string Field { get; set; }
}

and retrieve the value in Startup like

public void ConfigureServices(IServiceCollection services) {
    services.Configure<Section>(this.Configuration.GetSection("Section"));
}

The problem is that if for some reason (say misspelling) the binding fails, it is not going to throw, and instead it will create a Section object with null (default) value for the Field property.

Is there a way to make services.Configure<Section>(this.Configuration.GetSection("Section")); to throw if the binding fails?

Upvotes: 0

Views: 488

Answers (2)

havij
havij

Reputation: 1170

I am just summing up @Nkosi's answer here which makes this validation possible using data annotation.

1- Annotate the properties of your class:

public class Section
{
    [Required]
    public string Field { get; set; }
}

2- Create an extension method to enable validation to take effect:

public static class ConfigurationModelValidation
{
    public static T GetValid<T>(this IConfiguration configuration)
    {
        var obj = configuration.Get<T>();
        Validator.ValidateObject(obj, new ValidationContext(obj), true);
        return obj;
    }
}

3- In the Startup class, register you configuration models as below using GetValid method (instead of using 'IOptions'):

public void ConfigureServices(IServiceCollection services) {
    services.AddSingleton(this.Configuration.GetSection("Section").GetValid<Section>());
}

4- Now in the user's class directly inject your configuration model:

public class MyClass
{
    private readonly string field;

    public MyClass(Section section)
    {
        this.field = section.field;
    }
}

Now if binding fails for any reason, the validation will kick in and it will throw, enjoy!

Upvotes: 1

crgolden
crgolden

Reputation: 4634

You can just get the section first, then verify it exists (because it will not be null).

public void ConfigureServices(IServiceCollection services) {
    var section = this.Configuration.GetSection(nameof(Section));
    if (!section.Exists()) throw new Exception();
    services.Configure<Section>(section);
}

Upvotes: 0

Related Questions