3

I'm trying to use user secrets because I want to save my key AzureWebJobsStorage in secrets.json for local development.

  • So the problem is:

I created my user secrets, installed the necessary packages, but my webjob is still trying to use the keys in my appsettings.json.

What I accomplished so far:

I can read my secrets.json but I don't know where to go from here.

What have I tried

I have search through google but can't manage to find an answer. I saw similar questions here in StackOverflow but they refer to NetCore 2.0 or to something else not useful to me.

My files:

Program.cs

public class Program
{
    static async Task Main()
    {
        var builder = new HostBuilder();
        builder
        .UseEnvironment("Development")
        .ConfigureAppConfiguration((context, b) =>
        {
            if(context.HostingEnvironment.IsDevelopment())
                b.AddUserSecrets<Program>();
        })
        .ConfigureWebJobs(b =>
        {
            b.AddAzureStorageCoreServices();
            b.AddAzureStorage();
        })
        .ConfigureLogging((context, b) =>
        {
            b.AddConsole();
        })
        .ConfigureServices((context, b) =>
        {
            Infrastructure.IoC.DependencyResolver.RegisterServices(b, context.Configuration);
        });

        var host = builder.Build();
        using (host)
        {
            await host.RunAsync();
        }
    }
}

Functions.cs

public class Functions
{
    private readonly ITransactionService _transactionService;

    public Functions(ITransactionService transactionService)
    {
        _transactionService = transactionService;
    }

    public void ProcessQueueMessage([QueueTrigger("my_queue")] string message, ILogger logger)
    {
        try
        {
            Validate.IsTrue(long.TryParse(message, out long transactionId), "Invalid transaction from queue");
            _transactionService.CategorizeAllOtherTransactions(transactionId).Wait();
        }
        catch (System.Exception)
        {
            logger.LogInformation(message);
        }
    }
}

.csproj file:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <UserSecretsId>7f046fd1-a48c-4aa6-95db-009313bcb42b</UserSecretsId>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions" Version="3.0.6" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="4.0.2" />
    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="3.1.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.7" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\Yaba.Infrastructure.IoC\Yaba.Infrastructure.IoC.csproj" />
  </ItemGroup>

  <ItemGroup>
    <None Update="appsettings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • If you use Visual Studio 2019, once you add nuget 'Microsoft.Extensions.Configuration.UserSecrets' in your console .csproj (which you already did), "Manage User Secrets" option appears in right click of the project, just like asp.net core app. That will automatically configure your project. But in case you are not using VS 2019, let me look at what's going wrong in above. – krishg Sep 03 '20 at 04:03
  • I am using Visual Studio 2019. I already did that but my webjob is trying to use my `appsettings.json` instead. And [the documentation](https://learn.microsoft.com/pt-br/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1#security-and-secret-manager) says that secrets.json comes after appsettings.json when the application starts. – Vitor Ribeiro Sep 03 '20 at 20:33
  • As you know that secrets.json comes after appsettings.json when the application starts. Try delete the content of your appsettings.json? @VitorRibeiro – Doris Lv Sep 04 '20 at 03:01
  • Doesn't work neither. To test this I used a invalid azure key in `appsettings.json` and a valid one in `secrets.json` and it crashed. When I insert the valid key on `appsettings.json` it works fine. – Vitor Ribeiro Sep 04 '20 at 23:10

2 Answers2

2

As we discussed on GitHub, user secrets can be used to resolve the AzureWebJobsStorage value.

Key elements:

Program.cs

            builder.ConfigureAppConfiguration((context, configurationBuilder) =>
            {
                configurationBuilder
                    .AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: false)
                    .AddEnvironmentVariables();

                if (context.HostingEnvironment.IsDevelopment())
                {
                    configurationBuilder
                        .AddUserSecrets<Program>();
                }
            });

secrets.json:

{
  "ConnectionStrings": {
    "AzureWebJobsStorage": "..."
  }
}

launch.json:

{
  "profiles": {
    "WebJob-netcore-sample": {
      "commandName": "Project",
      "environmentVariables": {
        "DOTNET_ENVIRONMENT": "Development"
      }
    }
  }
}
Alex AIT
  • 17,361
  • 3
  • 36
  • 73
0

You could refer to the following code to get secrets value with Configuration["MyOptions:Secret1"].

public static IConfigurationRoot Configuration { get; set; }

static void Main(string[] args)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddEnvironmentVariables();
            
    builder.AddUserSecrets<Program>();
    Configuration = builder.Build();
    var a = Configuration["MyOptions:Secret1"];
}

public class MyOptions
{
    public string Secret1 { get; set; }
    public string Secret2 { get; set; }
}

The secrets.json is like below:

{
  "MyOptions": {
    "Secret1": "123",
    "Secret2": "456"
  }
}

Also, you could use following code in Main to get secrets value.

var services = new ServiceCollection()
    .Configure<MyOptions>(Configuration.GetSection(nameof(MyOptions)))
    .BuildServiceProvider();
var options = services.GetRequiredService<IOptions<MyOptions>>();
var b = options.Value.Secret1;
Joey Cai
  • 18,968
  • 1
  • 20
  • 30
  • The configuration works as I showed in the link in the description (click on _I can read my secrets.json_ in my question), but my webjob still tries to use `appsettings.json` instead. – Vitor Ribeiro Sep 03 '20 at 20:38
  • If you want to use it in azure webjobs, I suggest you could consider using Azure Key Vault. – Joey Cai Sep 09 '20 at 05:30