Creating the WebAPI–part 13

I am now tired of continuously improving the console application – so now some work that others can see really.  Creating the WebAPI is simple as a project  – and I was amazed to see a WeatherForecast controller.

I need just to be able to see the today exchange rates via API . So created a TodayRates , modify the launchSettings.json in order to start with my controller.

I need the plugin that loads to be a global dependency. So I add as a Singletion in the services

services.AddSingleton< LoadExchangeProviders>(new LoadExchangeProviders(“plugins”));

and then I inject into the controller constructor ( I can do in the method also, but many methods needs the same dependency )

public TodayRates(ILogger<TodayRates> logger, LoadExchangeProviders prov)
_logger = logger;
_prov = prov;


Now I need a method to see what are the banks / plugins that are loaded . Linq to the rescue :


public IEnumerable<string> Banks()
return _prov

Now we should load the data from the provider to show actual rates

public async IAsyncEnumerable<ExchangeRates> Rates(string bank)
var provBank = _prov
.FirstOrDefault(it => string.Equals(bank, it.Bank, StringComparison.InvariantCultureIgnoreCase));

switch (provBank)
case null:
yield return null;
await foreach (var data in provBank.GetActualRates())
yield return data;




All good. There are  3 problems:

  1. How to put the plugins for the console and web api ?
  2. How to cache the data  ? ( plugins / exchange rates)
  3. Should we throw an exception when a bank does not exists, instead of returning null ?


Thinking of this code, I realized that I begin to put logic into controllers. So – let’s move from the controller to the business.

For example, now I have this:

public IEnumerable<string> Banks()
return _prov.Banks();


And this

public IAsyncEnumerable<ExchangeRates> Rates(string bank)
return _prov.Rates(bank);

So now I can change in the Business Layer without problems.

Looking at the Console Application vs  WebAPI, I realized that are different. The console is loading the whole data from the providers – the WebAPI is loading on demand.  We could do for the console the same behavior  – but the console is loading very fast all data.

For the answer at

Should we throw an exception when a bank does not exists, instead of returning null ?

– seems to be yes.

So instead of

case null:
yield return null;
I put

case null:
throw new ArgumentOutOfRangeException(nameof(bank),$”cannot find {bank}”);


For the 2 questions, the answer next time.


And one hour passes...
(This is the result of 1 hour per day auto-challenge as a full cycle developer for an exchange rates application)
( You can see the sources at )
2Reading NBR from internet
3Source control and build
4Badge and test
5CI and action
6Artifacts and dotnet try
7Docker with .NET Try
9Intermezzo - Various implementations for programmers
10Intermezzo - similar code - options
11Plugin implementation
12GUI for console
14Plugin in .NET Core 3
15Build and Versioning
16Add swagger
17Docker - first part
18Docker - second part
19Docker - build Azure
20Pipeline send to Docker Hub
21Play with Docker - online
22Run VSCode and Docker
23Deploy Azure
24VSCode see tests and powershell
25Code Coverage
26Database in Azure
27Sql In Memory or Azure
28Azure ConString, RSS
29Middleware for backward compatibility