Let's say I have the following options structure

```cs
using System.ComponentModel.DataAnnotations;

public record AzureOption
{
    public AzureGraphOption? Graph { get; init; }
}

public record AzureGraphOption
{
    public AzureGraphSecretOption? Secret { get; init; }
}

public record AzureGraphSecretOption
{
    [Required] public string TenantId { get; init; }
    [Required] public string ClientId { get; init; }
    [Required] public string ClientSecret { get; init; }
}

```

And an extension class:

```cs
using Azure.Core;
using Azure.Identity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.Graph;

public static class AzureServiceExtensions
{
    // Add Azure services so we can query the Microsoft Graph and resolve membership for automatic group assignment
    public static IServiceCollection AddAzureServices(this IServiceCollection services)
    {
        services.AddAzureOptions();

        // Add a Azure Token Credentials based on "static" credentials
        // Requires a working Azure app and approvals for several permissions.
        // The app does not have to be operating on behalf of the user.
        services.AddScoped<TokenCredential>(provider =>
        {
            var azureOption = provider.GetRequiredService<IOptionsMonitor<AzureOption>>().CurrentValue;

            return new ClientSecretCredential(
                azureOption.Graph?.Secret?.TenantId,
                azureOption.Graph?.Secret?.ClientId,
                azureOption.Graph?.Secret?.ClientSecret,
                new TokenCredentialOptions
                {
                    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
                });
        });

        // Add the Microsoft Graph Service, based on the Azure Token
        services.AddScoped(provider => new GraphServiceClient(provider.GetService<TokenCredential>(),
            new[] { "https://graph.microsoft.com/.default" }));

        return services;
    }

    public static IServiceCollection AddAzureOptions(this IServiceCollection services)
    {
        services.AddOptions<AzureOption>()
            .BindConfiguration("Azure")
            .ValidateDataAnnotations()
            .ValidateOnStart();

        return services;
    }
}

```

And a small utility extension class:

```cs
using Microsoft.Extensions.Configuration;

public static class ServiceCollectionExtensions
{
    public static IConfigurationBuilder AddSecretConfig(this IConfigurationBuilder config)
    {
        config.AddJsonFile("appsettings.Secret.json", true, true);
        return config;
    }
}

```

We can also bootstrap a little ASP.NET Core app for testing, if you will:

```cs
using WebApplication = Microsoft.AspNetCore.Builder.WebApplication;

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddSecretConfig();

builder.Services
    .AddAzureServices();

var app = builder.Build();
app.Run();

```

I also have a small structure of secret file stored as `appsettings.Secret.json` in web root:

```json
{
  "Azure": {
    "Graph": {
      "Secret": {
        "TenantId": "30cbfa3f-a625-436a-90ff-e90c3fe8bb8e",
        "ClientId": "37c72790-ee45-4090-a749-c3ff61c43df8",
        "ClientSecret": "qqBGA~5QYza42ABjeWx4o-kAQPJKAGD38wVXCR7Y"
      }
    }
  }
}

```

It all went good and well, until I decided to delete the secrets:

```json
{
  "Azure": {
    "Graph": {
      "Secret": {
      }
    }
  }
}

```

However, the app still runs, and does not validate for the fields of `Azure:Graph:Secret`, because it is now `null` instead. Thus the `Required` validations attached on the fields never runs. If you have added a wrong property in `Azure:Graph:Secret`, this will happen too:

```cs
var azureOption = provider.GetRequiredService<IOptionsMonitor<AzureOption>>().CurrentValue;
var tenant = azureOption.Graph.Secret.TenantId; // What???! it is null???!

```

Of course, this is not desirable. I wanted to have this run dynamically:

```
var azureOption = provider.GetRequiredService<IOptionsMonitor<AzureOption>>().CurrentValue;
var tenant = azureOption.Graph.Secret.TenantId; // Throws an exception `Required value is not set` instead, while I don't have to handle nullable

```

One can always choose to add the nested options to match:

```cs
    public static IServiceCollection AddAzureOptions(this IServiceCollection services)
    {
        services.AddOptions<AzureOption>()
            .BindConfiguration("Azure")
            .ValidateDataAnnotations()
            .ValidateOnStart();

        services.AddOptions<AzureGraphSecretOption>()
            .BindConfiguration("Azure:Graph:Secret")
            .ValidateDataAnnotations()
            .ValidateOnStart();

        return services;
    }

```

But doing so is very tedious especially when you have tons of options.