Simon Price
Simon Price

Reputation: 3261

IOptionsMonitor<T> optionsAccessor null when an appsetting value is missing

I have a small issue with a a config setting, and 'IOptionsMonitor' CurrentValue being null when there is a missing \ empty value. The startup code is

var keySection = Configuration.GetSection("BlobStorageAccountKeys");
services.Configure<AzureBlobKeyConfiguration>(keySection);

The config is

"BlobStorageAccountKeys": {
  "Tenants": [
    {
      "AccountName": "firststorageaccount",
      "AccountKey": "xxxxxxxxxxxxxxxxhg5RCc5F0yE6OlxxxxxxxxxxxxxxxxxxWDj+jGsj31ayrxcTSTyJRYCtP2KdyVyWuMGd3A==",
      "DocumentTenantId": "b9b4062d-72b1-4be5-8abf-3f658ad25371"
    },
    {
      "AccountName": "secondstorageaccount",
      "AccountKey": "xxxxxxxxxxxTNJHGhg5RCc5F0yE6Ol5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxTyJRYCtP2KdyVyWuMGd3A==",
      "DocumentTenantId": ""
    }
  ]
},

This maps to

public class AzureBlobKeyConfiguration
{
    public AccountNameWithKey[] Tenants { get; set; }
}

public class AccountNameWithKey
{
    public string AccountName { get; set; }

    public string AccountKey { get; set; }

    public Guid DocumentTenantId { get; set; }
}

When running this method I get a null exception error

public class AzureBlobAsyncFileStore : IAsyncFileStore
{
    private readonly IAzureBlobServiceClientFactory _azureBlobServiceClientFactory;
    private readonly IOptionsMonitor<AzureBlobKeyConfiguration> _optionsAccessor;

    public AzureBlobAsyncFileStore(IAzureBlobServiceClientFactory azureBlobServiceClientFactory, IOptionsMonitor<AzureBlobKeyConfiguration> optionsAccessor)
    {
        _azureBlobServiceClientFactory = azureBlobServiceClientFactory ?? throw new ArgumentNullException(nameof(azureBlobServiceClientFactory));
        _optionsAccessor = optionsAccessor;
    }

    public async Task<string> StoreFileAsync(UploadToStorageRequest request, CancellationToken cancellationToken)
    {
        var accountDetails = _optionsAccessor.CurrentValue.Tenants; 
        var account = accountDetails.ToList().FirstOrDefault(account => account.DocumentTenantId == request.DocumentStoreTenantId); // If a value is missing in any apart of the config it has a null object and then throws a null excpetion reference 
        /// Code ommited
    }
}

I have a fix in place now var accountDetails = _optionsAccessor.CurrentValue.Tenants.Where(tenant => tenant != null).ToList() which gets me passed the issue and prevents this from happening, however I was \ am expecting an empty guid and the rest of the config value to be there.

I would be grateful if someone could let me know what I need to do or change to ensure that its not a null object in the array \ list of configuration.

--- Edit ---

enter image description here

--- Edit --- As per Poke comment, this is also where the issue was \ is prior to the fix being added and broke validation

public class UploadToStorageValidator : AbstractValidator<UploadToStorageRequest>
{
    private readonly IOptionsMonitor<AzureBlobKeyConfiguration> _optionsAccessor;

    public UploadToStorageValidator(IOptionsMonitor<AzureBlobKeyConfiguration> optionsAccessor)
    {
        _optionsAccessor = optionsAccessor;

        RuleFor(command => command.DocumentStoreTenantId).NotNull().NotEmpty().DependentRules(() =>
        {
            RuleFor(command => command.DocumentStoreTenantId).Custom(CheckTenantExists);
        });
    }

    private void CheckTenantExists(Guid tenantId, CustomContext customContext)
    {
        var tenants = _optionsAccessor.CurrentValue.Tenants;
        if (!tenants.Any(tenant => tenant.DocumentTenantId == tenantId))
        {
            customContext.AddFailure($"No tenant exists with Id : {tenantId}");
        }
    }
}

Upvotes: 1

Views: 991

Answers (0)

Related Questions