Skip to content

IValidateOptions and IConfigureOptions executing twice #71170

Open
@mshann03

Description

@mshann03

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

I've got a scenario where I'm using OptionsBuilderExtensions.ValidateOnStart to validate some settings to fail fast if there are any values missing etc.

I've wired in an IValidateOptions<> implementation to do the validation, and I have an IConfigureOptions<> implementation to change some of the settings on load.

The issue I'm experiencing is both the configure and validate implementations get called twice, and if I change any of the setting values in the first call to configure, it resets on the second call.

Here is a cutdown sample that illustrates my point:

Simple program.cs setup:

using Microsoft.Extensions.Options;
using OptionsValidationExample;

var builder = WebApplication.CreateBuilder(args);

builder
    .Services
    .AddOptions<GreetingSettings>()
    .Configure(settings => settings.Name = "Initial Name")
    .ValidateOnStart();

builder.Services.AddSingleton<IValidateOptions<GreetingSettings>, SettingsValidateOptions>();
builder.Services.AddSingleton<IConfigureOptions<GreetingSettings>, SettingsConfigureOptions>();
        
var app = builder.Build();

app.MapGet("/", (IOptions<GreetingSettings> settings) =>
{
    return $"Hello {settings.Value.Name}!";
});

app.Run();

And my GreetingSettings.cs file complete with validateoptions and configureoptions implementations:

using Microsoft.Extensions.Options;
using System.Diagnostics;

namespace OptionsValidationExample;

public class GreetingSettings
{
    public string Name { get; set; } = null!;
}

public class SettingsConfigureOptions : IConfigureOptions<GreetingSettings>
{
    public void Configure(GreetingSettings options)
    {
        // This method gets called twice due to ValidateOnStartup for the settings.
        Debugger.Break();

        // The second time it should come through as "Changed Name".
        Debug.Assert(options.Name == "Initial Name");

        options.Name = "Changed Name";
    }
}

public class SettingsValidateOptions : IValidateOptions<GreetingSettings>
{
    public ValidateOptionsResult Validate(string name, GreetingSettings options)
    {
        // This method gets called twice: once for ValidateOnStartup and once for first usage.
        Debugger.Break();

        return ValidateOptionsResult.Success;
    }
}

Any suggestions on how to fix this?

Many thanks in advance,
Mark.

Expected Behavior

I would have thought the validate would run once on startup, and further calls to any injected IOptions<>.value would not result in another validation.

Also, the fact that my IConfigureOptions implementation gets run on startup led me to expect the configure would not get called again after startup.

Steps To Reproduce

No response

Exceptions (if any)

No response

.NET Version

net6.0

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions