File: ApplicationModel\UserSecretsParameterDefault.cs
Web Access
Project: src\src\Aspire.Hosting\Aspire.Hosting.csproj (Aspire.Hosting)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
using System.Reflection;
using Aspire.Hosting.Publishing;
using Microsoft.Extensions.Configuration.UserSecrets;
using Microsoft.Extensions.SecretManager.Tools.Internal;
 
namespace Aspire.Hosting.ApplicationModel;
 
/// <summary>
/// Wraps a <see cref="ParameterDefault"/> such that the default value is saved to the project's user secrets store.
/// </summary>
/// <param name="appHostAssembly">The app host assembly.</param>
/// <param name="applicationName">The application name.</param>
/// <param name="parameterName">The parameter name.</param>
/// <param name="parameterDefault">The <see cref="ParameterDefault"/> that will produce the default value when it isn't found in the project's user secrets store.</param>
internal sealed class UserSecretsParameterDefault(Assembly appHostAssembly, string applicationName, string parameterName, ParameterDefault parameterDefault)
    : ParameterDefault
{
    /// <inheritdoc/>
    public override string GetDefaultValue()
    {
        var value = parameterDefault.GetDefaultValue();
        var configurationKey = $"Parameters:{parameterName}";
        if (!TrySetUserSecret(appHostAssembly, configurationKey, value))
        {
            // This is a best-effort operation, so we don't throw if it fails. Common reason for failure is that the user secrets ID is not set
            // in the application's assembly. Note there's no ILogger available this early in the application lifecycle.
            Debug.WriteLine($"Failed to set value for parameter '{parameterName}' in application '{applicationName}' to user secrets.");
        }
        return value;
    }
 
    /// <inheritdoc/>
    public override void WriteToManifest(ManifestPublishingContext context) => parameterDefault.WriteToManifest(context);
 
    private static bool TrySetUserSecret(Assembly assembly, string name, string value)
    {
        if (assembly.GetCustomAttribute<UserSecretsIdAttribute>()?.UserSecretsId is { } userSecretsId)
        {
            // Save the value to the secret store
            try
            {
                var secretsStore = new SecretsStore(userSecretsId);
                secretsStore.Set(name, value);
                secretsStore.Save();
                return true;
            }
            catch (Exception) { }
        }
 
        return false;
    }
}