Search code examples
c#asp.net-coremicrosoft-identity-platform

How to repeatedly call an REST API with JwtBearer token? Error: "Cannot change service once you call Build()"


I have followed this Microsoft tutorial titled "A .NET Core daemon console application calling a protected Web API with its own identity".

For my use case, I need to call the API multiple times. For example, I may need to change the GET query parameters in the URI.

This is where the tutorial has me confused, particularly the portion below. The primary issue is that I can only call .Build() once before receiving this error, "Cannot change service once you call Build()". And I may not know the API ".Configuration" parameters the first time I call it.

This code is from the Microsoft tutorial

// Get the Token acquirer factory instance. By default it reads an appsettings.json
// file if it exists in the same folder as the app (make sure that the 
// "Copy to Output Directory" property of the appsettings.json file is "Copy if newer").
var tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();

// Add console logging or other services if you wish
tokenAcquirerFactory.Services.AddLogging(
    (loggingBuilder) => loggingBuilder.SetMinimumLevel(LogLevel.Warning)
                                      .AddConsole()
                                        );

// Create a downstream API service named 'MyApi' which comes loaded with several
// utility methods to make HTTP calls to the DownstreamApi configurations found
// in the "MyWebApi" section of your appsettings.json file.
tokenAcquirerFactory.Services.AddDownstreamApi("MyApi",
    tokenAcquirerFactory.Configuration.GetSection("MyWebApi"));
var sp = tokenAcquirerFactory.Build();

// Extract the downstream API service from the 'tokenAcquirerFactory' service provider.
var api = sp.GetRequiredService<IDownstreamApi>();

// You can use the API service to make direct HTTP calls to your API. Token
// acquisition is handled automatically based on the configurations in your
// appsettings.json file.
var result = await api.GetForAppAsync<IEnumerable<TodoItem>>("MyApi");
Console.WriteLine($"result = {result?.Count()}");

I am also shocked the function used in the tutorial api.GetForAppAsync has only 6 hits in Google, instead of the millions of hits that typically occur. Surely, I am missing something...

How can I change the "Configuration" parameters of "TokenAcquireFactory" and only call "tokenAcquirerFactory.Build();" once without receiving the error in the question title?


Solution

  • Use the "options" syntax, as demonstrated here. You can change the ".RelativePath" and other variables after the ".Build()".

    var result = api.GetForAppAsync<List<string>>(
        "MyApi",
        options =>
        {
            options.RelativePath += $"?siteId={mySiteId}";
        }).Result;
    

    Microsoft reference